Bug 490957. Eliminate nsWebShell. r+sr=bsmedberg
authorBoris Zbarsky <bzbarsky@mit.edu>
Thu, 07 May 2009 15:21:53 -0400
changeset 28078 53eebf02eac766300426cb0d386eb4a61564cd61
parent 28077 89338a224278a839b3c6f79a7e46f13235ee8911
child 28079 6aa0cb2a52fb28ddc616b4c0ecb910e26c8d83c4
push id6886
push userbzbarsky@mozilla.com
push dateThu, 07 May 2009 19:24:34 +0000
treeherdermozilla-central@55339f8d68fa [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs490957
milestone1.9.2a1pre
Bug 490957. Eliminate nsWebShell. r+sr=bsmedberg
content/base/src/nsDocument.cpp
content/base/src/nsFrameLoader.cpp
docshell/base/Makefile.in
docshell/base/nsCDocShell.idl
docshell/base/nsDocShell.cpp
docshell/base/nsDocShell.h
docshell/base/nsIDocShell.idl
docshell/base/nsWebShell.cpp
docshell/base/nsWebShell.h
docshell/build/nsDocShellCID.h
docshell/build/nsDocShellModule.cpp
editor/composer/src/nsEditingSession.cpp
editor/composer/src/nsEditorParserObserver.cpp
editor/composer/src/nsEditorParserObserver.h
embedding/browser/webBrowser/nsWebBrowser.cpp
intl/chardet/public/nsICharsetDetectionAdaptor.h
intl/chardet/src/nsMetaCharsetObserver.cpp
intl/chardet/src/nsObserverBase.cpp
intl/chardet/src/nsObserverBase.h
intl/chardet/src/nsXMLEncodingObserver.cpp
intl/chardet/src/nsXMLEncodingObserver.h
layout/base/nsCSSFrameConstructor.cpp
layout/base/nsDocumentViewer.cpp
modules/plugin/base/src/nsPluginHostImpl.cpp
parser/htmlparser/public/nsIElementObserver.h
parser/htmlparser/public/nsIParserService.h
parser/htmlparser/src/nsDTDUtils.cpp
parser/htmlparser/src/nsDTDUtils.h
toolkit/components/viewsource/content/viewSourceUtils.js
xpfe/appshell/src/nsWebShellWindow.cpp
xpfe/browser/src/nsBrowserInstance.cpp
--- a/content/base/src/nsDocument.cpp
+++ b/content/base/src/nsDocument.cpp
@@ -1981,18 +1981,21 @@ nsDocument::ResetToURI(nsIURI *aURI, nsI
   mDOMStyleSheets = nsnull;
 
   SetDocumentURI(aURI);
   mDocumentBaseURI = mDocumentURI;
 
   if (aLoadGroup) {
     mDocumentLoadGroup = do_GetWeakReference(aLoadGroup);
     // there was an assertion here that aLoadGroup was not null.  This
-    // is no longer valid nsWebShell::SetDocument does not create a
-    // load group, and it works just fine.
+    // is no longer valid: nsDocShell::SetDocument does not create a
+    // load group, and it works just fine
+
+    // XXXbz what does "just fine" mean exactly?  And given that there
+    // is no nsDocShell::SetDocument, what is this talking about?
   }
 
   mLastModified.Truncate();
   // XXXbz I guess we're assuming that the caller will either pass in
   // a channel with a useful type or call SetContentType?
   mContentType.Truncate();
   mContentLanguage.Truncate();
   mBaseTarget.Truncate();
--- a/content/base/src/nsFrameLoader.cpp
+++ b/content/base/src/nsFrameLoader.cpp
@@ -401,17 +401,17 @@ AddTreeItemToTreeOwner(nsIDocShellTreeIt
     StringBeginsWith(value, NS_LITERAL_STRING("content-"),
                      nsCaseInsensitiveStringComparator());
 
   if (isContent) {
     // The web shell's type is content.
 
     aItem->SetItemType(nsIDocShellTreeItem::typeContent);
   } else {
-    // Inherit our type from our parent webshell.  If it is
+    // Inherit our type from our parent docshell.  If it is
     // chrome, we'll be chrome.  If it is content, we'll be
     // content.
 
     aItem->SetItemType(aParentType);
   }
 
   // Now that we have our type set, add ourselves to the parent, as needed.
   if (aParentNode) {
@@ -803,17 +803,17 @@ nsFrameLoader::EnsureDocShell()
     // Don't allow subframe loads in external reference documents
     return NS_ERROR_NOT_AVAILABLE;
   }
 
   nsCOMPtr<nsIWebNavigation> parentAsWebNav =
     do_GetInterface(doc->GetScriptGlobalObject());
 
   // Create the docshell...
-  mDocShell = do_CreateInstance("@mozilla.org/webshell;1");
+  mDocShell = do_CreateInstance("@mozilla.org/docshell;1");
   NS_ENSURE_TRUE(mDocShell, NS_ERROR_FAILURE);
 
   // Get the frame name and tell the docshell about it.
   nsCOMPtr<nsIDocShellTreeItem> docShellAsItem(do_QueryInterface(mDocShell));
   NS_ENSURE_TRUE(docShellAsItem, NS_ERROR_FAILURE);
   nsAutoString frameName;
 
   PRInt32 namespaceID = mOwnerContent->GetNameSpaceID();
--- a/docshell/base/Makefile.in
+++ b/docshell/base/Makefile.in
@@ -88,17 +88,16 @@ REQUIRES	= xpcom \
 		  prefetch \
 		  $(NULL)
 
 SDK_XPIDLSRCS = \
 		nsIGlobalHistory.idl \
 		$(NULL)
 
 XPIDLSRCS	= \
-		nsCDocShell.idl			\
 		nsCDefaultURIFixup.idl		\
 		nsIDocShell.idl			\
 		nsIDocShellLoadInfo.idl	\
 		nsIDocShellTreeItem.idl	\
 		nsIDocShellTreeNode.idl	\
 		nsIDocShellTreeOwner.idl	\
 		nsIDocShellHistory.idl \
 		nsIGlobalHistory2.idl \
@@ -119,17 +118,16 @@ XPIDLSRCS	= \
 		nsIDownloadHistory.idl          \
 		nsILoadContext.idl              \
 		$(NULL)
 
 EXPORTS		= nsDocShellLoadTypes.h
 
 CPPSRCS		= \
 		nsDocShell.cpp		\
-		nsWebShell.cpp		\
 		nsDocShellLoadInfo.cpp		\
 		nsDocShellEditorData.cpp	\
 		nsDocShellTransferableHooks.cpp \
 		nsDocShellEnumerator.cpp  \
 		nsDSURIContentListener.cpp		\
 		nsDefaultURIFixup.cpp		\
 		nsGlobalHistoryAdapter.cpp \
 		nsGlobalHistory2Adapter.cpp \
deleted file mode 100644
--- a/docshell/base/nsCDocShell.idl
+++ /dev/null
@@ -1,64 +0,0 @@
-/* -*- Mode: IDL; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
- *
- * ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is the Mozilla browser.
- *
- * The Initial Developer of the Original Code is
- * Netscape Communications, Inc.
- * Portions created by the Initial Developer are Copyright (C) 1999
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *   Travis Bogard <travis@netscape.com>
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either of the GNU General Public License Version 2 or later (the "GPL"),
- * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-#include "nsIDocShell.idl"
-#include "nsIDocShellTreeItem.idl"
-#include "nsIDocShellTreeNode.idl"
-#include "nsIBaseWindow.idl"
-#include "nsIScrollable.idl"
-#include "nsITextScroll.idl"
-
-/*
-nsCHTMLDocShell implements:
--------------------------
-nsIDocShell
-nsIDocShellTreeItem
-nsIDocShellTreeNode
-nsIBaseWindow
-nsIScrollable
-nsITextScroll
-*/
-
-%{ C++
-//  {F1EAC762-87E9-11d3-AF80-00A024FFC08C} - 
-#define NS_DOCSHELL_CID \
-{ 0xf1eac762, 0x87e9, 0x11d3, { 0xaf, 0x80, 0x00, 0xa0, 0x24, 0xff, 0xc0, 0x8c } }
-#define NS_DOCSHELL_CONTRACTID \
-"@mozilla.org/docshell/html;1"
-%}
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -144,16 +144,21 @@
 #include "nsIObserver.h"
 #include "nsINestedURI.h"
 #include "nsITransportSecurityInfo.h"
 #include "nsINSSErrorsService.h"
 #include "nsIApplicationCache.h"
 #include "nsIApplicationCacheChannel.h"
 #include "nsIApplicationCacheContainer.h"
 #include "nsIPermissionManager.h"
+#include "nsStreamUtils.h"
+#include "nsIController.h"
+#include "nsPICommandUpdater.h"
+#include "nsIDOMHTMLAnchorElement.h"
+#include "nsIWebBrowserChrome2.h"
 
 // Editor-related
 #include "nsIEditingSession.h"
 
 #include "nsPIDOMWindow.h"
 #include "nsIDOMDocument.h"
 #include "nsICachingChannel.h"
 #include "nsICacheVisitor.h"
@@ -274,19 +279,412 @@ protected:
 
 private:
   static nsDocShellFocusController mDocShellFocusControllerSingleton;
 };
 
 nsDocShellFocusController nsDocShellFocusController::mDocShellFocusControllerSingleton;
 
 //*****************************************************************************
+// <a ping> support
+//*****************************************************************************
+
+#define PREF_PINGS_ENABLED           "browser.send_pings"
+#define PREF_PINGS_MAX_PER_LINK      "browser.send_pings.max_per_link"
+#define PREF_PINGS_REQUIRE_SAME_HOST "browser.send_pings.require_same_host"
+
+// Check prefs to see if pings are enabled and if so what restrictions might
+// be applied.
+//
+// @param maxPerLink
+//   This parameter returns the number of pings that are allowed per link click
+//
+// @param requireSameHost
+//   This parameter returns PR_TRUE if pings are restricted to the same host as
+//   the document in which the click occurs.  If the same host restriction is
+//   imposed, then we still allow for pings to cross over to different
+//   protocols and ports for flexibility and because it is not possible to send
+//   a ping via FTP.
+//
+// @returns
+//   PR_TRUE if pings are enabled and PR_FALSE otherwise.
+//
+static PRBool
+PingsEnabled(PRInt32 *maxPerLink, PRBool *requireSameHost)
+{
+  PRBool allow = PR_FALSE;
+
+  *maxPerLink = 1;
+  *requireSameHost = PR_TRUE;
+
+  nsCOMPtr<nsIPrefBranch> prefs =
+      do_GetService(NS_PREFSERVICE_CONTRACTID);
+  if (prefs) {
+    PRBool val;
+    if (NS_SUCCEEDED(prefs->GetBoolPref(PREF_PINGS_ENABLED, &val)))
+      allow = val;
+    if (allow) {
+      prefs->GetIntPref(PREF_PINGS_MAX_PER_LINK, maxPerLink);
+      prefs->GetBoolPref(PREF_PINGS_REQUIRE_SAME_HOST, requireSameHost);
+    }
+  }
+
+  return allow;
+}
+
+static PRBool
+CheckPingURI(nsIURI* uri, nsIContent* content)
+{
+  if (!uri)
+    return PR_FALSE;
+
+  // Check with nsIScriptSecurityManager
+  nsCOMPtr<nsIScriptSecurityManager> ssmgr =
+    do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID);
+  NS_ENSURE_TRUE(ssmgr, PR_FALSE);
+
+  nsresult rv =
+    ssmgr->CheckLoadURIWithPrincipal(content->NodePrincipal(), uri,
+                                     nsIScriptSecurityManager::STANDARD);
+  if (NS_FAILED(rv)) {
+    return PR_FALSE;
+  }
+
+  // Ignore non-HTTP(S)
+  PRBool match;
+  if ((NS_FAILED(uri->SchemeIs("http", &match)) || !match) &&
+      (NS_FAILED(uri->SchemeIs("https", &match)) || !match)) {
+    return PR_FALSE;
+  }
+
+  // Check with contentpolicy
+  PRInt16 shouldLoad = nsIContentPolicy::ACCEPT;
+  rv = NS_CheckContentLoadPolicy(nsIContentPolicy::TYPE_PING,
+                                 uri,
+                                 content->NodePrincipal(),
+                                 content,
+                                 EmptyCString(), // mime hint
+                                 nsnull, //extra
+                                 &shouldLoad);
+  return NS_SUCCEEDED(rv) && NS_CP_ACCEPTED(shouldLoad);
+}
+
+typedef void (* ForEachPingCallback)(void *closure, nsIContent *content,
+                                     nsIURI *uri, nsIIOService *ios);
+
+static void
+ForEachPing(nsIContent *content, ForEachPingCallback callback, void *closure)
+{
+  // NOTE: Using nsIDOMNSHTMLAnchorElement2::GetPing isn't really worth it here
+  //       since we'd still need to parse the resulting string.  Instead, we
+  //       just parse the raw attribute.  It might be nice if the content node
+  //       implemented an interface that exposed an enumeration of nsIURIs.
+
+  // Make sure we are dealing with either an <A> or <AREA> element in the HTML
+  // or XHTML namespace.
+  if (!content->IsNodeOfType(nsINode::eHTML))
+    return;
+  nsIAtom *nameAtom = content->Tag();
+  if (!nameAtom->EqualsUTF8(NS_LITERAL_CSTRING("a")) &&
+      !nameAtom->EqualsUTF8(NS_LITERAL_CSTRING("area")))
+    return;
+
+  nsCOMPtr<nsIAtom> pingAtom = do_GetAtom("ping");
+  if (!pingAtom)
+    return;
+
+  nsAutoString value;
+  content->GetAttr(kNameSpaceID_None, pingAtom, value);
+  if (value.IsEmpty())
+    return;
+
+  nsCOMPtr<nsIIOService> ios = do_GetIOService();
+  if (!ios)
+    return;
+
+  nsIDocument *doc = content->GetOwnerDoc();
+  if (!doc)
+    return;
+
+  // value contains relative URIs split on spaces (U+0020)
+  const PRUnichar *start = value.BeginReading();
+  const PRUnichar *end   = value.EndReading();
+  const PRUnichar *iter  = start;
+  for (;;) {
+    if (iter < end && *iter != ' ') {
+      ++iter;
+    } else {  // iter is pointing at either end or a space
+      while (*start == ' ' && start < iter)
+        ++start;
+      if (iter != start) {
+        nsCOMPtr<nsIURI> uri, baseURI = content->GetBaseURI();
+        ios->NewURI(NS_ConvertUTF16toUTF8(Substring(start, iter)),
+                    doc->GetDocumentCharacterSet().get(),
+                    baseURI, getter_AddRefs(uri));
+        if (CheckPingURI(uri, content)) {
+          callback(closure, content, uri, ios);
+        }
+      }
+      start = iter = iter + 1;
+      if (iter >= end)
+        break;
+    }
+  }
+}
+
+//----------------------------------------------------------------------
+
+// We wait this many milliseconds before killing the ping channel...
+#define PING_TIMEOUT 10000
+
+static void
+OnPingTimeout(nsITimer *timer, void *closure)
+{
+  nsILoadGroup *loadGroup = static_cast<nsILoadGroup *>(closure);
+  loadGroup->Cancel(NS_ERROR_ABORT);
+  loadGroup->Release();
+}
+
+// Check to see if two URIs have the same host or not
+static PRBool
+IsSameHost(nsIURI *uri1, nsIURI *uri2)
+{
+  nsCAutoString host1, host2;
+  uri1->GetAsciiHost(host1);
+  uri2->GetAsciiHost(host2);
+  return host1.Equals(host2);
+}
+
+class nsPingListener : public nsIStreamListener
+                     , public nsIInterfaceRequestor
+                     , public nsIChannelEventSink
+{
+public:
+  NS_DECL_ISUPPORTS
+  NS_DECL_NSIREQUESTOBSERVER
+  NS_DECL_NSISTREAMLISTENER
+  NS_DECL_NSIINTERFACEREQUESTOR
+  NS_DECL_NSICHANNELEVENTSINK
+
+  nsPingListener(PRBool requireSameHost, nsIContent* content)
+    : mRequireSameHost(requireSameHost),
+      mContent(content)
+  {}
+
+private:
+  PRBool mRequireSameHost;
+  nsCOMPtr<nsIContent> mContent;
+};
+
+NS_IMPL_ISUPPORTS4(nsPingListener, nsIStreamListener, nsIRequestObserver,
+                   nsIInterfaceRequestor, nsIChannelEventSink)
+
+NS_IMETHODIMP
+nsPingListener::OnStartRequest(nsIRequest *request, nsISupports *context)
+{
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsPingListener::OnDataAvailable(nsIRequest *request, nsISupports *context,
+                                nsIInputStream *stream, PRUint32 offset,
+                                PRUint32 count)
+{
+  PRUint32 result;
+  return stream->ReadSegments(NS_DiscardSegment, nsnull, count, &result);
+}
+
+NS_IMETHODIMP
+nsPingListener::OnStopRequest(nsIRequest *request, nsISupports *context,
+                              nsresult status)
+{
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsPingListener::GetInterface(const nsIID &iid, void **result)
+{
+  if (iid.Equals(NS_GET_IID(nsIChannelEventSink))) {
+    NS_ADDREF_THIS();
+    *result = (nsIChannelEventSink *) this;
+    return NS_OK;
+  }
+
+  return NS_ERROR_NO_INTERFACE;
+}
+
+NS_IMETHODIMP
+nsPingListener::OnChannelRedirect(nsIChannel *oldChan, nsIChannel *newChan,
+                                  PRUint32 flags)
+{
+  nsCOMPtr<nsIURI> newURI;
+  newChan->GetURI(getter_AddRefs(newURI));
+
+  if (!CheckPingURI(newURI, mContent))
+    return NS_ERROR_ABORT;
+
+  if (!mRequireSameHost)
+    return NS_OK;
+
+  // XXXbz should this be using something more like the nsContentUtils
+  // same-origin checker?
+  nsCOMPtr<nsIURI> oldURI;
+  oldChan->GetURI(getter_AddRefs(oldURI));
+  NS_ENSURE_STATE(oldURI && newURI);
+
+  if (!IsSameHost(oldURI, newURI))
+    return NS_ERROR_ABORT;
+
+  return NS_OK;
+}
+
+struct SendPingInfo {
+  PRInt32 numPings;
+  PRInt32 maxPings;
+  PRBool  requireSameHost;
+  nsIURI *referrer;
+};
+
+static void
+SendPing(void *closure, nsIContent *content, nsIURI *uri, nsIIOService *ios)
+{
+  SendPingInfo *info = static_cast<SendPingInfo *>(closure);
+  if (info->numPings >= info->maxPings)
+    return;
+
+  if (info->requireSameHost) {
+    // Make sure the referrer and the given uri share the same origin.  We
+    // only require the same hostname.  The scheme and port may differ.
+    if (!IsSameHost(uri, info->referrer))
+      return;
+  }
+
+  nsIDocument *doc = content->GetOwnerDoc();
+  if (!doc)
+    return;
+
+  nsCOMPtr<nsIChannel> chan;
+  ios->NewChannelFromURI(uri, getter_AddRefs(chan));
+  if (!chan)
+    return;
+
+  // Don't bother caching the result of this URI load.
+  chan->SetLoadFlags(nsIRequest::INHIBIT_CACHING);
+
+  nsCOMPtr<nsIHttpChannel> httpChan = do_QueryInterface(chan);
+  if (!httpChan)
+    return;
+
+  // This is needed in order for 3rd-party cookie blocking to work.
+  nsCOMPtr<nsIHttpChannelInternal> httpInternal = do_QueryInterface(httpChan);
+  if (httpInternal)
+    httpInternal->SetDocumentURI(doc->GetDocumentURI());
+
+  if (info->referrer)
+    httpChan->SetReferrer(info->referrer);
+
+  httpChan->SetRequestMethod(NS_LITERAL_CSTRING("POST"));
+
+  // Remove extraneous request headers (to reduce request size)
+  httpChan->SetRequestHeader(NS_LITERAL_CSTRING("accept"),
+                             EmptyCString(), PR_FALSE);
+  httpChan->SetRequestHeader(NS_LITERAL_CSTRING("accept-language"),
+                             EmptyCString(), PR_FALSE);
+  httpChan->SetRequestHeader(NS_LITERAL_CSTRING("accept-charset"),
+                             EmptyCString(), PR_FALSE);
+  httpChan->SetRequestHeader(NS_LITERAL_CSTRING("accept-encoding"),
+                             EmptyCString(), PR_FALSE);
+
+  nsCOMPtr<nsIUploadChannel> uploadChan = do_QueryInterface(httpChan);
+  if (!uploadChan)
+    return;
+
+  // To avoid sending an unnecessary Content-Type header, we encode the
+  // closing portion of the headers in the POST body.
+  NS_NAMED_LITERAL_CSTRING(uploadData, "Content-Length: 0\r\n\r\n");
+
+  nsCOMPtr<nsIInputStream> uploadStream;
+  NS_NewPostDataStream(getter_AddRefs(uploadStream), PR_FALSE,
+                       uploadData, 0);
+  if (!uploadStream)
+    return;
+
+  uploadChan->SetUploadStream(uploadStream, EmptyCString(), -1);
+
+  // The channel needs to have a loadgroup associated with it, so that we can
+  // cancel the channel and any redirected channels it may create.
+  nsCOMPtr<nsILoadGroup> loadGroup =
+      do_CreateInstance(NS_LOADGROUP_CONTRACTID);
+  if (!loadGroup)
+    return;
+  chan->SetLoadGroup(loadGroup);
+
+  // Construct a listener that merely discards any response.  If successful at
+  // opening the channel, then it is not necessary to hold a reference to the
+  // channel.  The networking subsystem will take care of that for us.
+  nsCOMPtr<nsIStreamListener> listener =
+      new nsPingListener(info->requireSameHost, content);
+  if (!listener)
+    return;
+
+  // Observe redirects as well:
+  nsCOMPtr<nsIInterfaceRequestor> callbacks = do_QueryInterface(listener);
+  NS_ASSERTION(callbacks, "oops");
+  loadGroup->SetNotificationCallbacks(callbacks);
+
+  chan->AsyncOpen(listener, nsnull);
+
+  // Even if AsyncOpen failed, we still count this as a successful ping.  It's
+  // possible that AsyncOpen may have failed after triggering some background
+  // process that may have written something to the network.
+  info->numPings++;
+
+  // Prevent ping requests from stalling and never being garbage collected...
+  nsCOMPtr<nsITimer> timer =
+      do_CreateInstance(NS_TIMER_CONTRACTID);
+  if (timer) {
+    nsresult rv = timer->InitWithFuncCallback(OnPingTimeout, loadGroup,
+                                              PING_TIMEOUT,
+                                              nsITimer::TYPE_ONE_SHOT);
+    if (NS_SUCCEEDED(rv)) {
+      // When the timer expires, the callback function will release this
+      // reference to the loadgroup.
+      static_cast<nsILoadGroup *>(loadGroup.get())->AddRef();
+      loadGroup = 0;
+    }
+  }
+  
+  // If we failed to setup the timer, then we should just cancel the channel
+  // because we won't be able to ensure that it goes away in a timely manner.
+  if (loadGroup)
+    chan->Cancel(NS_ERROR_ABORT);
+}
+
+// Spec: http://whatwg.org/specs/web-apps/current-work/#ping
+static void
+DispatchPings(nsIContent *content, nsIURI *referrer)
+{
+  SendPingInfo info;
+
+  if (!PingsEnabled(&info.maxPings, &info.requireSameHost))
+    return;
+  if (info.maxPings == 0)
+    return;
+
+  info.numPings = 0;
+  info.referrer = referrer;
+
+  ForEachPing(content, SendPing, &info);
+}
+
+//*****************************************************************************
 //***    nsDocShell: Object Management
 //*****************************************************************************
 
+// Note: operator new zeros our memory
 nsDocShell::nsDocShell():
     nsDocLoader(),
     mAllowSubframes(PR_TRUE),
     mAllowPlugins(PR_TRUE),
     mAllowJavascript(PR_TRUE),
     mAllowMetaRedirects(PR_TRUE),
     mAllowImages(PR_TRUE),
     mFocusDocFirst(PR_FALSE),
@@ -302,24 +700,25 @@ nsDocShell::nsDocShell():
     mURIResultedInDocument(PR_FALSE),
     mIsBeingDestroyed(PR_FALSE),
     mIsExecutingOnLoadHandler(PR_FALSE),
     mIsPrintingOrPP(PR_FALSE),
     mSavingOldViewer(PR_FALSE),
     mAppType(nsIDocShell::APP_TYPE_UNKNOWN),
     mChildOffset(0),
     mBusyFlags(BUSY_FLAGS_NONE),
-    mMarginWidth(0),
-    mMarginHeight(0),
+    mMarginWidth(-1),
+    mMarginHeight(-1),
     mItemType(typeContent),
     mDefaultScrollbarPref(Scrollbar_Auto, Scrollbar_Auto),
     mPreviousTransIndex(-1),
     mLoadedTransIndex(-1),
     mTreeOwner(nsnull),
-    mChromeEventHandler(nsnull)
+    mChromeEventHandler(nsnull),
+    mCharsetReloadState(eCharsetReloadInit)
 #ifdef DEBUG
     , mInEnsureScriptEnv(PR_FALSE)
 #endif
 {
     if (gDocShellCount++ == 0) {
         NS_ASSERTION(sURIFixup == nsnull,
                      "Huh, sURIFixup not null in first nsDocShell ctor!");
 
@@ -331,16 +730,24 @@ nsDocShell::nsDocShell():
     if (! gDocShellLog)
         gDocShellLog = PR_NewLogModule("nsDocShell");
 #endif
     if (nsnull == gDocShellLeakLog)
         gDocShellLeakLog = PR_NewLogModule("nsDocShellLeak");
     if (gDocShellLeakLog)
         PR_LOG(gDocShellLeakLog, PR_LOG_DEBUG, ("DOCSHELL %p created\n", this));
 #endif
+
+#ifdef DEBUG
+  // We're counting the number of |nsDocShells| to help find leaks
+  ++gNumberOfDocShells;
+#endif
+#ifdef DEBUG
+  printf("++DOCSHELL %p == %ld\n", (void*) this, gNumberOfDocShells);
+#endif
 }
 
 nsDocShell::~nsDocShell()
 {
     nsDocShellFocusController* dsfc = nsDocShellFocusController::GetInstance();
     if (dsfc) {
       dsfc->ClosingDown(this);
     }
@@ -349,16 +756,24 @@ nsDocShell::~nsDocShell()
     if (--gDocShellCount == 0) {
         NS_IF_RELEASE(sURIFixup);
     }
 
 #ifdef PR_LOGGING
     if (gDocShellLeakLog)
         PR_LOG(gDocShellLeakLog, PR_LOG_DEBUG, ("DOCSHELL %p destroyed\n", this));
 #endif
+
+#ifdef DEBUG
+    // We're counting the number of |nsDocShells| to help find leaks
+    --gNumberOfDocShells;
+#endif
+#ifdef DEBUG
+    printf("--DOCSHELL %p == %ld\n", (void*) this, gNumberOfDocShells);
+#endif
 }
 
 nsresult
 nsDocShell::Init()
 {
     nsresult rv = nsDocLoader::Init();
     NS_ENSURE_SUCCESS(rv, rv);
 
@@ -433,28 +848,35 @@ NS_INTERFACE_MAP_BEGIN(nsDocShell)
     NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
     NS_INTERFACE_MAP_ENTRY(nsIContentViewerContainer)
     NS_INTERFACE_MAP_ENTRY(nsIEditorDocShell)
     NS_INTERFACE_MAP_ENTRY(nsIWebPageDescriptor)
     NS_INTERFACE_MAP_ENTRY(nsIAuthPromptProvider)
     NS_INTERFACE_MAP_ENTRY(nsIObserver)
     NS_INTERFACE_MAP_ENTRY(nsILoadContext)
     NS_INTERFACE_MAP_ENTRY(nsIDocShell_MOZILLA_1_9_1)
+    NS_INTERFACE_MAP_ENTRY(nsIWebShellServices)
+    NS_INTERFACE_MAP_ENTRY(nsILinkHandler)
+    NS_INTERFACE_MAP_ENTRY(nsIClipboardCommands)
 NS_INTERFACE_MAP_END_INHERITING(nsDocLoader)
 
 ///*****************************************************************************
 // nsDocShell::nsIInterfaceRequestor
 //*****************************************************************************   
 NS_IMETHODIMP nsDocShell::GetInterface(const nsIID & aIID, void **aSink)
 {
     NS_PRECONDITION(aSink, "null out param");
 
     *aSink = nsnull;
 
-    if (aIID.Equals(NS_GET_IID(nsIURIContentListener))) {
+    if (aIID.Equals(NS_GET_IID(nsICommandManager))) {
+        NS_ENSURE_SUCCESS(EnsureCommandHandler(), NS_ERROR_FAILURE);
+        *aSink = mCommandManager;
+    }
+    else if (aIID.Equals(NS_GET_IID(nsIURIContentListener))) {
         *aSink = mContentListener;
     }
     else if (aIID.Equals(NS_GET_IID(nsIScriptGlobalObject)) &&
              NS_SUCCEEDED(EnsureScriptEnvironment())) {
         *aSink = mScriptGlobal;
     }
     else if ((aIID.Equals(NS_GET_IID(nsIDOMWindowInternal)) ||
               aIID.Equals(NS_GET_IID(nsPIDOMWindow)) ||
@@ -3534,26 +3956,16 @@ nsDocShell::Stop(PRUint32 aStopFlags)
         nsCOMPtr<nsIWebNavigation> shellAsNav(do_QueryInterface(ChildAt(n)));
         if (shellAsNav)
             shellAsNav->Stop(aStopFlags);
     }
 
     return NS_OK;
 }
 
-/*
-NS_IMETHODIMP nsDocShell::SetDocument(nsIDOMDocument* aDocument,
-   const PRUnichar* aContentType)
-{
-   //XXX First Checkin
-   NS_ERROR("Not Yet Implemented");
-   return NS_ERROR_FAILURE;
-}
-*/
-
 NS_IMETHODIMP
 nsDocShell::GetDocument(nsIDOMDocument ** aDocument)
 {
     NS_ENSURE_ARG_POINTER(aDocument);
     NS_ENSURE_SUCCESS(EnsureContentViewer(), NS_ERROR_FAILURE);
 
     return mContentViewer->GetDOMDocument(aDocument);
 }
@@ -3707,16 +4119,21 @@ nsDocShell::InitWindow(nativeWindow pare
     SetPositionAndSize(x, y, cx, cy, PR_FALSE);
 
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDocShell::Create()
 {
+    if (mPrefs) {
+        // We've already been created
+        return NS_OK;
+    }
+
     NS_ASSERTION(mItemType == typeContent || mItemType == typeChrome,
                  "Unexpected item type in docshell");
 
     nsresult rv = NS_ERROR_FAILURE;
     mPrefs = do_GetService(NS_PREFSERVICE_CONTRACTID, &rv);
     NS_ENSURE_SUCCESS(rv, rv);
 
     PRBool tmpbool;
@@ -4361,17 +4778,17 @@ nsDocShell::SetScrollRangeEx(PRInt32 min
 
        @return NS_OK - Setting or Getting completed successfully.
        NS_ERROR_INVALID_ARG - returned when curPos is not within the
        minPos and maxPos.
      */
     return NS_ERROR_FAILURE;
 }
 
-// This returns setting for all documents in this webshell
+// This returns setting for all documents in this docshell
 NS_IMETHODIMP
 nsDocShell::GetDefaultScrollbarPreferences(PRInt32 scrollOrientation,
                                            PRInt32 * scrollbarPref)
 {
     NS_ENSURE_ARG_POINTER(scrollbarPref);
     switch (scrollOrientation) {
     case ScrollOrientation_X:
         *scrollbarPref = mDefaultScrollbarPref.x;
@@ -5248,16 +5665,34 @@ nsDocShell::OnSecurityChange(nsIWebProgr
     return NS_OK;
 }
 
 
 nsresult
 nsDocShell::EndPageLoad(nsIWebProgress * aProgress,
                         nsIChannel * aChannel, nsresult aStatus)
 {
+    if(!aChannel)
+        return NS_ERROR_NULL_POINTER;
+    
+    nsCOMPtr<nsIURI> url;
+    nsresult rv = aChannel->GetURI(getter_AddRefs(url));
+    if (NS_FAILED(rv)) return rv;
+  
+    // clean up reload state for meta charset
+    if (eCharsetReloadRequested == mCharsetReloadState)
+        mCharsetReloadState = eCharsetReloadStopOrigional;
+    else 
+        mCharsetReloadState = eCharsetReloadInit;
+
+    // Save a pointer to the currently-loading history entry.
+    // nsDocShell::EndPageLoad will clear mLSHE, but we may need this history
+    // entry further down in this method.
+    nsCOMPtr<nsISHEntry> loadingSHE = mLSHE;
+  
     //
     // one of many safeguards that prevent death and destruction if
     // someone is so very very rude as to bring this window down
     // during this load handler.
     //
     nsCOMPtr<nsIDocShell> kungFuDeathGrip(this);
 
     // We're done with the URI classifier for this channel
@@ -5310,17 +5745,295 @@ nsDocShell::EndPageLoad(nsIWebProgress *
         // Clear the mLSHE reference to indicate document loading is done one
         // way or another.
         SetHistoryEntry(&mLSHE, nsnull);
     }
     // if there's a refresh header in the channel, this method
     // will set it up for us. 
     RefreshURIFromQueue();
 
-    return NS_OK;
+    // Test whether this is the top frame or a subframe
+    PRBool isTopFrame = PR_TRUE;
+    nsCOMPtr<nsIDocShellTreeItem> targetParentTreeItem;
+    rv = GetSameTypeParent(getter_AddRefs(targetParentTreeItem));
+    if (NS_SUCCEEDED(rv) && targetParentTreeItem) {
+        isTopFrame = PR_FALSE;
+    }
+
+    //
+    // If the page load failed, then deal with the error condition...
+    // Errors are handled as follows:
+    //   1. Check to see if it's a file not found error or bad content
+    //      encoding error.
+    //   2. Send the URI to a keyword server (if enabled)
+    //   3. If the error was DNS failure, then add www and .com to the URI
+    //      (if appropriate).
+    //   4. Throw an error dialog box...
+    //
+    if (url && NS_FAILED(aStatus)) {
+        if (aStatus == NS_ERROR_FILE_NOT_FOUND ||
+            aStatus == NS_ERROR_INVALID_CONTENT_ENCODING) {
+            DisplayLoadError(aStatus, url, nsnull, aChannel);
+            return NS_OK;
+        }
+
+        if (sURIFixup) {
+            //
+            // Try and make an alternative URI from the old one
+            //
+            nsCOMPtr<nsIURI> newURI;
+
+            nsCAutoString oldSpec;
+            url->GetSpec(oldSpec);
+      
+            //
+            // First try keyword fixup
+            //
+            if (aStatus == NS_ERROR_UNKNOWN_HOST && mAllowKeywordFixup) {
+                PRBool keywordsEnabled = PR_FALSE;
+
+                if (mPrefs &&
+                    NS_FAILED(mPrefs->GetBoolPref("keyword.enabled",
+                                                  &keywordsEnabled)))
+                    keywordsEnabled = PR_FALSE;
+
+                nsCAutoString host;
+                url->GetHost(host);
+
+                nsCAutoString scheme;
+                url->GetScheme(scheme);
+
+                PRInt32 dotLoc = host.FindChar('.');
+
+                // we should only perform a keyword search under the following
+                // conditions:
+                // (0) Pref keyword.enabled is true
+                // (1) the url scheme is http (or https)
+                // (2) the url does not have a protocol scheme
+                // If we don't enforce such a policy, then we end up doing
+                // keyword searchs on urls we don't intend like imap, file,
+                // mailbox, etc. This could lead to a security problem where we
+                // send data to the keyword server that we shouldn't be.
+                // Someone needs to clean up keywords in general so we can
+                // determine on a per url basis if we want keywords
+                // enabled...this is just a bandaid...
+                if (keywordsEnabled && !scheme.IsEmpty() &&
+                    (scheme.Find("http") != 0)) {
+                    keywordsEnabled = PR_FALSE;
+                }
+
+                if (keywordsEnabled && (kNotFound == dotLoc)) {
+                    // only send non-qualified hosts to the keyword server
+                    //
+                    // If this string was passed through nsStandardURL by
+                    // chance, then it may have been converted from UTF-8 to
+                    // ACE, which would result in a completely bogus keyword
+                    // query.  Here we try to recover the original Unicode
+                    // value, but this is not 100% correct since the value may
+                    // have been normalized per the IDN normalization rules.
+                    //
+                    // Since we don't have access to the exact original string
+                    // that was entered by the user, this will just have to do.
+                    PRBool isACE;
+                    nsCAutoString utf8Host;
+                    nsCOMPtr<nsIIDNService> idnSrv =
+                        do_GetService(NS_IDNSERVICE_CONTRACTID);
+                    if (idnSrv &&
+                        NS_SUCCEEDED(idnSrv->IsACE(host, &isACE)) && isACE &&
+                        NS_SUCCEEDED(idnSrv->ConvertACEtoUTF8(host, utf8Host)))
+                        sURIFixup->KeywordToURI(utf8Host,
+                                                getter_AddRefs(newURI));
+                    else
+                        sURIFixup->KeywordToURI(host, getter_AddRefs(newURI));
+                } // end keywordsEnabled
+            }
+
+            //
+            // Now try change the address, e.g. turn http://foo into
+            // http://www.foo.com
+            //
+            if (aStatus == NS_ERROR_UNKNOWN_HOST ||
+                aStatus == NS_ERROR_NET_RESET) {
+                PRBool doCreateAlternate = PR_TRUE;
+
+                // Skip fixup for anything except a normal document load
+                // operation on the topframe.
+        
+                if (mLoadType != LOAD_NORMAL || !isTopFrame) {
+                    doCreateAlternate = PR_FALSE;
+                }
+                else {
+                    // Test if keyword lookup produced a new URI or not
+                    if (newURI) {
+                        PRBool sameURI = PR_FALSE;
+                        url->Equals(newURI, &sameURI);
+                        if (!sameURI) {
+                            // Keyword lookup made a new URI so no need to try
+                            // an alternate one.
+                            doCreateAlternate = PR_FALSE;
+                        }
+                    }
+                }
+                if (doCreateAlternate) {
+                    newURI = nsnull;
+                    sURIFixup->CreateFixupURI(oldSpec,
+                      nsIURIFixup::FIXUP_FLAGS_MAKE_ALTERNATE_URI,
+                                              getter_AddRefs(newURI));
+                }
+            }
+
+            // Did we make a new URI that is different to the old one? If so
+            // load it.
+            //
+            if (newURI) {
+                // Make sure the new URI is different from the old one,
+                // otherwise there's little point trying to load it again.
+                PRBool sameURI = PR_FALSE;
+                url->Equals(newURI, &sameURI);
+                if (!sameURI) {
+                    nsCAutoString newSpec;
+                    newURI->GetSpec(newSpec);
+                    NS_ConvertUTF8toUTF16 newSpecW(newSpec);
+
+                    return LoadURI(newSpecW.get(),  // URI string
+                                   LOAD_FLAGS_NONE, // Load flags
+                                   nsnull,          // Referring URI
+                                   nsnull,          // Post data stream
+                                   nsnull);         // Headers stream
+                }
+            }
+        }
+
+        // Well, fixup didn't work :-(
+        // It is time to throw an error dialog box, and be done with it...
+
+        // Errors to be shown only on top-level frames
+        if ((aStatus == NS_ERROR_UNKNOWN_HOST || 
+             aStatus == NS_ERROR_CONNECTION_REFUSED ||
+             aStatus == NS_ERROR_UNKNOWN_PROXY_HOST || 
+             aStatus == NS_ERROR_PROXY_CONNECTION_REFUSED) &&
+            (isTopFrame || mUseErrorPages)) {
+            DisplayLoadError(aStatus, url, nsnull, aChannel);
+        }
+        // Errors to be shown for any frame
+        else if (aStatus == NS_ERROR_NET_TIMEOUT ||
+                 aStatus == NS_ERROR_REDIRECT_LOOP ||
+                 aStatus == NS_ERROR_UNKNOWN_SOCKET_TYPE ||
+                 aStatus == NS_ERROR_NET_INTERRUPT ||
+                 aStatus == NS_ERROR_NET_RESET ||
+                 aStatus == NS_ERROR_MALWARE_URI ||
+                 aStatus == NS_ERROR_PHISHING_URI ||
+                 aStatus == NS_ERROR_UNSAFE_CONTENT_TYPE ||
+                 NS_ERROR_GET_MODULE(aStatus) == NS_ERROR_MODULE_SECURITY) {
+            DisplayLoadError(aStatus, url, nsnull, aChannel);
+        }
+        else if (aStatus == NS_ERROR_DOCUMENT_NOT_CACHED) {
+            /* A document that was requested to be fetched *only* from
+             * the cache is not in cache. May be this is one of those 
+             * postdata results. Throw a  dialog to the user,
+             * saying that the page has expired from cache and ask if 
+             * they wish to refetch the page from the net. Do this only
+             * if the request is a form post.
+             */
+            nsCAutoString method;
+            if (httpChannel)
+                httpChannel->GetRequestMethod(method);
+            if (method.Equals("POST") && !NS_IsOffline()) {
+                PRBool repost;
+                rv = ConfirmRepost(&repost);
+                if (NS_FAILED(rv)) return rv;
+                // If the user pressed cancel in the dialog, return. Don't try
+                // to load the page without the post data.
+                if (!repost)
+                    return NS_OK;
+
+                // The user wants to repost the data to the server.
+                // If the page was loaded due to a back/forward/go
+                // operation, update the session history index.
+                // This is similar to the updating done in
+                // nsDocShell::OnNewURI() for regular pages
+                nsCOMPtr<nsISHistory> rootSH=mSessionHistory;
+                if (!mSessionHistory) {
+                    nsCOMPtr<nsIDocShellTreeItem> root;
+                    //Get the root docshell
+                    GetSameTypeRootTreeItem(getter_AddRefs(root));
+                    if (root) {
+                        // QI root to nsIWebNavigation
+                        nsCOMPtr<nsIWebNavigation> rootAsWebnav =
+                            do_QueryInterface(root);
+                        if (rootAsWebnav) {
+                            // Get the handle to SH from the root docshell
+                            rootAsWebnav->GetSessionHistory(getter_AddRefs(rootSH));
+                        }
+                    }
+                }  // mSessionHistory
+
+                if (rootSH && (mLoadType & LOAD_CMD_HISTORY)) {
+                    nsCOMPtr<nsISHistoryInternal> shInternal =
+                        do_QueryInterface(rootSH);
+                    if (shInternal) {
+                        rootSH->GetIndex(&mPreviousTransIndex);
+                        shInternal->UpdateIndex();
+                        rootSH->GetIndex(&mLoadedTransIndex);
+#ifdef DEBUG_PAGE_CACHE
+                        printf("Previous index: %d, Loaded index: %d\n\n",
+                               mPreviousTransIndex, mLoadedTransIndex);
+#endif
+                    }
+                }
+
+                // Make it look like we really did honestly finish loading the
+                // history page we were loading, since the "reload" load we're
+                // about to kick off will reload our current history entry.
+                // This is a bit of a hack, and if the force-load fails I think
+                // we'll end up being confused about what page we're on... but
+                // we would anyway, since we've updated the session history
+                // index above.
+                SetHistoryEntry(&mOSHE, loadingSHE);
+
+                // The user does want to repost the data to the server.
+                // Initiate a new load again.
+
+                // Get the postdata if any from the channel.
+                nsCOMPtr<nsIInputStream> inputStream;
+                nsCOMPtr<nsIURI> referrer;
+                if (httpChannel) {
+                    httpChannel->GetReferrer(getter_AddRefs(referrer));
+                    nsCOMPtr<nsIUploadChannel> uploadChannel =
+                        do_QueryInterface(aChannel);
+                    if (uploadChannel) {
+                        uploadChannel->GetUploadStream(getter_AddRefs(inputStream));
+                    }
+                }
+                nsCOMPtr<nsISeekableStream> postDataSeekable =
+                    do_QueryInterface(inputStream);
+                if (postDataSeekable) {
+                    postDataSeekable->Seek(nsISeekableStream::NS_SEEK_SET, 0);
+                }
+                InternalLoad(url,                               // URI
+                             referrer,                          // Referring URI
+                             nsnull,                            // Owner
+                             INTERNAL_LOAD_FLAGS_INHERIT_OWNER, // Inherit owner
+                             nsnull,                            // No window target
+                             nsnull,                            // No type hint
+                             inputStream,                       // Post data stream
+                             nsnull,                            // No headers stream
+                             LOAD_RELOAD_BYPASS_PROXY_AND_CACHE,// Load type
+                             nsnull,                            // No SHEntry
+                             PR_TRUE,                           // first party site
+                             nsnull,                            // No nsIDocShell
+                             nsnull);                           // No nsIRequest
+            }
+            else {
+                DisplayLoadError(aStatus, url, nsnull, aChannel);
+            }
+        }
+  } // if we have a host
+
+  return NS_OK;
 }
 
 
 //*****************************************************************************
 // nsDocShell: Content Viewer Management
 //*****************************************************************************   
 
 NS_IMETHODIMP
@@ -9995,8 +10708,485 @@ nsClassifierCallback::GetInterface(const
         *aResult = static_cast<nsIChannelEventSink *>(this);
         return NS_OK;
     } else if (mNotificationCallbacks) {
         return mNotificationCallbacks->GetInterface(aIID, aResult);
     } else {
         return NS_ERROR_NO_INTERFACE;
     }
 }
+
+//
+// Routines for selection and clipboard
+//
+nsresult
+nsDocShell::GetControllerForCommand(const char * inCommand,
+                                    nsIController** outController)
+{
+  NS_ENSURE_ARG_POINTER(outController);
+  *outController = nsnull;
+  
+  nsresult rv = NS_ERROR_FAILURE;
+  
+  nsCOMPtr<nsPIDOMWindow> window ( do_QueryInterface(mScriptGlobal) );
+  if (window) {
+    nsIFocusController *focusController = window->GetRootFocusController();
+    if (focusController)
+      rv = focusController->GetControllerForCommand (inCommand, outController);
+  } // if window
+
+  return rv;
+  
+}
+
+nsresult
+nsDocShell::IsCommandEnabled(const char * inCommand, PRBool* outEnabled)
+{
+  NS_ENSURE_ARG_POINTER(outEnabled);
+  *outEnabled = PR_FALSE;
+
+  nsresult rv = NS_ERROR_FAILURE;
+  
+  nsCOMPtr<nsIController> controller;
+  rv = GetControllerForCommand (inCommand, getter_AddRefs(controller));
+  if (controller)
+    rv = controller->IsCommandEnabled(inCommand, outEnabled);
+  
+  return rv;
+}
+
+nsresult
+nsDocShell::DoCommand(const char * inCommand)
+{
+  nsresult rv = NS_ERROR_FAILURE;
+  
+  nsCOMPtr<nsIController> controller;
+  rv = GetControllerForCommand(inCommand, getter_AddRefs(controller));
+  if (controller)
+    rv = controller->DoCommand(inCommand);
+  
+  return rv;
+}
+
+nsresult
+nsDocShell::EnsureCommandHandler()
+{
+  if (!mCommandManager)
+  {
+    nsCOMPtr<nsPICommandUpdater> commandUpdater =
+      do_CreateInstance("@mozilla.org/embedcomp/command-manager;1");
+    if (!commandUpdater) return NS_ERROR_OUT_OF_MEMORY;
+    
+    nsCOMPtr<nsIDOMWindow> domWindow =
+      do_GetInterface(static_cast<nsIInterfaceRequestor *>(this));
+
+    nsresult rv = commandUpdater->Init(domWindow);
+    if (NS_SUCCEEDED(rv))
+      mCommandManager = do_QueryInterface(commandUpdater);
+  }
+  
+  return mCommandManager ? NS_OK : NS_ERROR_FAILURE;
+}
+
+NS_IMETHODIMP
+nsDocShell::CanCutSelection(PRBool* aResult)
+{
+  return IsCommandEnabled("cmd_cut", aResult);
+}
+
+NS_IMETHODIMP
+nsDocShell::CanCopySelection(PRBool* aResult)
+{
+  return IsCommandEnabled("cmd_copy", aResult);
+}
+
+NS_IMETHODIMP
+nsDocShell::CanCopyLinkLocation(PRBool* aResult)
+{
+  return IsCommandEnabled("cmd_copyLink", aResult);
+}
+
+NS_IMETHODIMP
+nsDocShell::CanCopyImageLocation(PRBool* aResult)
+{
+  return IsCommandEnabled("cmd_copyImageLocation",
+                          aResult);
+}
+
+NS_IMETHODIMP
+nsDocShell::CanCopyImageContents(PRBool* aResult)
+{
+  return IsCommandEnabled("cmd_copyImageContents",
+                          aResult);
+}
+
+NS_IMETHODIMP
+nsDocShell::CanPaste(PRBool* aResult)
+{
+  return IsCommandEnabled("cmd_paste", aResult);
+}
+
+NS_IMETHODIMP
+nsDocShell::CutSelection(void)
+{
+  return DoCommand ( "cmd_cut" );
+}
+
+NS_IMETHODIMP
+nsDocShell::CopySelection(void)
+{
+  return DoCommand ( "cmd_copy" );
+}
+
+NS_IMETHODIMP
+nsDocShell::CopyLinkLocation(void)
+{
+  return DoCommand ( "cmd_copyLink" );
+}
+
+NS_IMETHODIMP
+nsDocShell::CopyImageLocation(void)
+{
+  return DoCommand ( "cmd_copyImageLocation" );
+}
+
+NS_IMETHODIMP
+nsDocShell::CopyImageContents(void)
+{
+  return DoCommand ( "cmd_copyImageContents" );
+}
+
+NS_IMETHODIMP
+nsDocShell::Paste(void)
+{
+  return DoCommand ( "cmd_paste" );
+}
+
+NS_IMETHODIMP
+nsDocShell::SelectAll(void)
+{
+  return DoCommand ( "cmd_selectAll" );
+}
+
+//
+// SelectNone
+//
+// Collapses the current selection, insertion point ends up at beginning
+// of previous selection.
+//
+NS_IMETHODIMP
+nsDocShell::SelectNone(void)
+{
+  return DoCommand ( "cmd_selectNone" );
+}
+
+//----------------------------------------------------------------------
+
+// link handling
+
+class OnLinkClickEvent : public nsRunnable {
+public:
+  OnLinkClickEvent(nsDocShell* aHandler, nsIContent* aContent,
+                   nsIURI* aURI,
+                   const PRUnichar* aTargetSpec,
+                   nsIInputStream* aPostDataStream = 0, 
+                   nsIInputStream* aHeadersDataStream = 0);
+
+  NS_IMETHOD Run() {
+    nsCOMPtr<nsPIDOMWindow> window(do_QueryInterface(mHandler->mScriptGlobal));
+    nsAutoPopupStatePusher popupStatePusher(window, mPopupState);
+
+    mHandler->OnLinkClickSync(mContent, mURI,
+                              mTargetSpec.get(), mPostDataStream,
+                              mHeadersDataStream,
+                              nsnull, nsnull);
+    return NS_OK;
+  }
+
+private:
+  nsRefPtr<nsDocShell>     mHandler;
+  nsCOMPtr<nsIURI>         mURI;
+  nsString                 mTargetSpec;
+  nsCOMPtr<nsIInputStream> mPostDataStream;
+  nsCOMPtr<nsIInputStream> mHeadersDataStream;
+  nsCOMPtr<nsIContent>     mContent;
+  PopupControlState        mPopupState;
+};
+
+OnLinkClickEvent::OnLinkClickEvent(nsDocShell* aHandler,
+                                   nsIContent *aContent,
+                                   nsIURI* aURI,
+                                   const PRUnichar* aTargetSpec,
+                                   nsIInputStream* aPostDataStream,
+                                   nsIInputStream* aHeadersDataStream)
+  : mHandler(aHandler)
+  , mURI(aURI)
+  , mTargetSpec(aTargetSpec)
+  , mPostDataStream(aPostDataStream)
+  , mHeadersDataStream(aHeadersDataStream)
+  , mContent(aContent)
+{
+  nsCOMPtr<nsPIDOMWindow> window(do_QueryInterface(mHandler->mScriptGlobal));
+
+  mPopupState = window->GetPopupControlState();
+}
+
+//----------------------------------------
+
+NS_IMETHODIMP
+nsDocShell::OnLinkClick(nsIContent* aContent,
+                        nsIURI* aURI,
+                        const PRUnichar* aTargetSpec,
+                        nsIInputStream* aPostDataStream,
+                        nsIInputStream* aHeadersDataStream)
+{
+  NS_ASSERTION(NS_IsMainThread(), "wrong thread");
+
+  if (!IsOKToLoadURI(aURI)) {
+    return NS_OK;
+  }
+
+  if (aContent->IsEditable()) {
+    return NS_OK;
+  }
+
+  nsCOMPtr<nsIRunnable> ev =
+      new OnLinkClickEvent(this, aContent, aURI, aTargetSpec,
+                           aPostDataStream, aHeadersDataStream);
+  return NS_DispatchToCurrentThread(ev);
+}
+
+NS_IMETHODIMP
+nsDocShell::OnLinkClickSync(nsIContent *aContent,
+                            nsIURI* aURI,
+                            const PRUnichar* aTargetSpec,
+                            nsIInputStream* aPostDataStream,
+                            nsIInputStream* aHeadersDataStream,
+                            nsIDocShell** aDocShell,
+                            nsIRequest** aRequest)
+{
+  // Initialize the DocShell / Request
+  if (aDocShell) {
+    *aDocShell = nsnull;
+  }
+  if (aRequest) {
+    *aRequest = nsnull;
+  }
+
+  if (!IsOKToLoadURI(aURI)) {
+    return NS_OK;
+  }
+
+  if (aContent->IsEditable()) {
+    return NS_OK;
+  }
+
+  {
+    // defer to an external protocol handler if necessary...
+    nsCOMPtr<nsIExternalProtocolService> extProtService =
+        do_GetService(NS_EXTERNALPROTOCOLSERVICE_CONTRACTID);
+    if (extProtService) {
+      nsCAutoString scheme;
+      aURI->GetScheme(scheme);
+      if (!scheme.IsEmpty()) {
+        // if the URL scheme does not correspond to an exposed protocol, then we
+        // need to hand this link click over to the external protocol handler.
+        PRBool isExposed;
+        nsresult rv = extProtService->IsExposedProtocol(scheme.get(), &isExposed);
+        if (NS_SUCCEEDED(rv) && !isExposed) {
+          return extProtService->LoadURI(aURI, this); 
+        }
+      }
+    }
+  }
+
+  // Get the owner document of the link that was clicked, this will be
+  // the document that the link is in, or the last document that the
+  // link was in. From that document, we'll get the URI to use as the
+  // referer, since the current URI in this docshell may be a
+  // new document that we're in the process of loading.
+  nsCOMPtr<nsIDocument> refererDoc = aContent->GetOwnerDoc();
+  NS_ENSURE_TRUE(refererDoc, NS_ERROR_UNEXPECTED);
+
+  nsCOMPtr<nsIURI> referer = refererDoc->GetDocumentURI();
+
+  // referer could be null here in some odd cases, but that's ok,
+  // we'll just load the link w/o sending a referer in those cases.
+
+  nsAutoString target(aTargetSpec);
+
+  // If this is an anchor element, grab its type property to use as a hint
+  nsAutoString typeHint;
+  nsCOMPtr<nsIDOMHTMLAnchorElement> anchor(do_QueryInterface(aContent));
+  if (anchor) {
+    anchor->GetType(typeHint);
+  }
+  
+  nsresult rv = InternalLoad(aURI,                      // New URI
+                             referer,                   // Referer URI
+                             aContent->NodePrincipal(), // Owner is our node's
+                                                        // principal
+                             INTERNAL_LOAD_FLAGS_NONE,
+                             target.get(),              // Window target
+                             NS_LossyConvertUTF16toASCII(typeHint).get(),
+                             aPostDataStream,           // Post data stream
+                             aHeadersDataStream,        // Headers stream
+                             LOAD_LINK,                 // Load type
+                             nsnull,                    // No SHEntry
+                             PR_TRUE,                   // first party site
+                             aDocShell,                 // DocShell out-param
+                             aRequest);                 // Request out-param
+  if (NS_SUCCEEDED(rv)) {
+    DispatchPings(aContent, referer);
+  }
+  return rv;
+}
+
+NS_IMETHODIMP
+nsDocShell::OnOverLink(nsIContent* aContent,
+                       nsIURI* aURI,
+                       const PRUnichar* aTargetSpec)
+{
+  if (aContent->IsEditable()) {
+    return NS_OK;
+  }
+
+  nsCOMPtr<nsIWebBrowserChrome2> browserChrome2 = do_GetInterface(mTreeOwner);
+  nsresult rv = NS_ERROR_FAILURE;
+
+  nsCOMPtr<nsIWebBrowserChrome> browserChrome;
+  if (!browserChrome2) {
+    browserChrome = do_GetInterface(mTreeOwner);
+    if (!browserChrome)
+      return rv;
+  }
+
+  nsCOMPtr<nsITextToSubURI> textToSubURI =
+      do_GetService(NS_ITEXTTOSUBURI_CONTRACTID, &rv);
+  if (NS_FAILED(rv))
+    return rv;
+
+  // use url origin charset to unescape the URL
+  nsCAutoString charset;
+  rv = aURI->GetOriginCharset(charset);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  nsCAutoString spec;
+  rv = aURI->GetSpec(spec);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  nsAutoString uStr;
+  rv = textToSubURI->UnEscapeURIForUI(charset, spec, uStr);    
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  if (browserChrome2) {
+    nsCOMPtr<nsIDOMElement> element = do_QueryInterface(aContent);
+    rv = browserChrome2->SetStatusWithContext(nsIWebBrowserChrome::STATUS_LINK,
+                                              uStr, element);
+  } else {
+    rv = browserChrome->SetStatus(nsIWebBrowserChrome::STATUS_LINK, uStr.get());
+  }
+  return rv;
+}
+
+NS_IMETHODIMP
+nsDocShell::OnLeaveLink()
+{
+  nsCOMPtr<nsIWebBrowserChrome> browserChrome(do_GetInterface(mTreeOwner));
+  nsresult rv = NS_ERROR_FAILURE;
+
+  if (browserChrome)  {
+      rv = browserChrome->SetStatus(nsIWebBrowserChrome::STATUS_LINK,
+                                    EmptyString().get());
+  }
+  return rv;
+}
+
+NS_IMETHODIMP
+nsDocShell::GetLinkState(nsIURI* aLinkURI, nsLinkState& aState)
+{
+  if (!aLinkURI) {
+    // No uri means not a link
+    aState = eLinkState_NotLink;
+    return NS_OK;
+  }
+    
+  aState = eLinkState_Unvisited;
+
+  // no history, leave state unchanged
+  if (!mGlobalHistory)
+    return NS_OK;
+
+  PRBool isVisited;
+  NS_ENSURE_SUCCESS(mGlobalHistory->IsVisited(aLinkURI, &isVisited),
+                    NS_ERROR_FAILURE);
+  if (isVisited)
+    aState = eLinkState_Visited;
+  
+  return NS_OK;
+}
+
+//----------------------------------------------------------------------
+// Web Shell Services API
+
+//This functions is only called when a new charset is detected in loading a document. 
+//Its name should be changed to "CharsetReloadDocument"
+NS_IMETHODIMP
+nsDocShell::ReloadDocument(const char* aCharset,
+                           PRInt32 aSource)
+{
+
+  // XXX hack. kee the aCharset and aSource wait to pick it up
+  nsCOMPtr<nsIContentViewer> cv;
+  NS_ENSURE_SUCCESS(GetContentViewer(getter_AddRefs(cv)), NS_ERROR_FAILURE);
+  if (cv)
+  {
+    nsCOMPtr<nsIMarkupDocumentViewer> muDV = do_QueryInterface(cv);  
+    if (muDV)
+    {
+      PRInt32 hint;
+      muDV->GetHintCharacterSetSource(&hint);
+      if( aSource > hint ) 
+      {
+         muDV->SetHintCharacterSet(nsDependentCString(aCharset));
+         muDV->SetHintCharacterSetSource(aSource);
+         if(eCharsetReloadRequested != mCharsetReloadState) 
+         {
+            mCharsetReloadState = eCharsetReloadRequested;
+            return Reload(LOAD_FLAGS_CHARSET_CHANGE);
+         }
+      }
+    }
+  }
+  //return failer if this request is not accepted due to mCharsetReloadState
+  return NS_ERROR_DOCSHELL_REQUEST_REJECTED;
+}
+
+
+NS_IMETHODIMP
+nsDocShell::StopDocumentLoad(void)
+{
+  if(eCharsetReloadRequested != mCharsetReloadState) 
+  {
+    Stop(nsIWebNavigation::STOP_ALL);
+    return NS_OK;
+  }
+  //return failer if this request is not accepted due to mCharsetReloadState
+  return NS_ERROR_DOCSHELL_REQUEST_REJECTED;
+}
+
+NS_IMETHODIMP
+nsDocShell::SetRendering(PRBool aRender)
+{
+  if(eCharsetReloadRequested != mCharsetReloadState) 
+  {
+    if (mContentViewer) {
+       mContentViewer->SetEnableRendering(aRender);
+       return NS_OK;
+    }
+  }
+  //return failer if this request is not accepted due to mCharsetReloadState
+  return NS_ERROR_DOCSHELL_REQUEST_REJECTED;
+}
+
+#ifdef DEBUG
+unsigned long nsDocShell::gNumberOfDocShells = 0;
+#endif
--- a/docshell/base/nsDocShell.h
+++ b/docshell/base/nsDocShell.h
@@ -45,17 +45,22 @@
 #include "nsIDOMNode.h"
 #include "nsIDOMNodeList.h"
 #include "nsIContentViewer.h"
 #include "nsIPrefBranch.h"
 #include "nsInterfaceHashtable.h"
 #include "nsIScriptContext.h"
 #include "nsITimer.h"
 
-#include "nsCDocShell.h"
+#include "nsIDocShell.h"
+#include "nsIDocShellTreeItem.h"
+#include "nsIDocShellTreeNode.h"
+#include "nsIBaseWindow.h"
+#include "nsIScrollable.h"
+#include "nsITextScroll.h"
 #include "nsIDocShellTreeOwner.h"
 #include "nsIContentViewerContainer.h"
 #include "nsIDeviceContext.h"
 
 #include "nsDocLoader.h"
 #include "nsIURILoader.h"
 #include "nsIEditorDocShell.h"
 
@@ -103,19 +108,26 @@
 #include "nsISecureBrowserUI.h"
 #include "nsIObserver.h"
 #include "nsDocShellLoadTypes.h"
 #include "nsPIDOMEventTarget.h"
 #include "nsIURIClassifier.h"
 #include "nsIChannelClassifier.h"
 #include "nsILoadContext.h"
 #include "nsIWidget.h"
+#include "nsIWebShellServices.h"
+#include "nsILinkHandler.h"
+#include "nsIClipboardCommands.h"
+#include "nsICommandManager.h"
+#include "nsCRT.h"
 
 class nsIScrollableView;
 class nsDocShell;
+class nsIController;
+class OnLinkClickEvent;
 
 /* load commands were moved to nsIDocShell.h */
 /* load types were moved to nsDocShellLoadTypes.h */
 
 /* internally used ViewMode types */
 enum ViewMode {
     viewNormal = 0x0,
     viewSource = 0x1
@@ -166,16 +178,24 @@ private:
     nsCOMPtr<nsIChannel> mChannel;
     nsCOMPtr<nsIChannel> mSuspendedChannel;
     nsCOMPtr<nsIInterfaceRequestor> mNotificationCallbacks;
 
     void MarkEntryClassified(nsresult status);
     PRBool HasBeenClassified(nsIChannel *aChannel);
 };
 
+#define NS_ERROR_DOCSHELL_REQUEST_REJECTED  NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_GENERAL,1001)
+
+typedef enum {
+    eCharsetReloadInit,
+    eCharsetReloadRequested,
+    eCharsetReloadStopOrigional
+} eCharsetReloadState;
+
 //*****************************************************************************
 //***    nsDocShell
 //*****************************************************************************
 
 class nsDocShell : public nsDocLoader,
                    public nsIDocShell,
                    public nsIDocShellTreeItem, 
                    public nsIDocShellHistory,
@@ -188,24 +208,29 @@ class nsDocShell : public nsDocLoader,
                    public nsIScriptGlobalObjectOwner,
                    public nsIRefreshURI,
                    public nsIWebProgressListener,
                    public nsIEditorDocShell,
                    public nsIWebPageDescriptor,
                    public nsIAuthPromptProvider,
                    public nsIObserver,
                    public nsILoadContext,
-                   public nsIDocShell_MOZILLA_1_9_1
+                   public nsIDocShell_MOZILLA_1_9_1,
+                   public nsIWebShellServices,
+                   public nsILinkHandler,
+                   public nsIClipboardCommands
 {
-friend class nsDSURIContentListener;
+    friend class nsDSURIContentListener;
 
 public:
     // Object Management
     nsDocShell();
 
+    NS_DECL_AND_IMPL_ZEROING_OPERATOR_NEW
+
     virtual nsresult Init();
 
     NS_DECL_ISUPPORTS_INHERITED
 
     NS_DECL_NSIDOCSHELL
     NS_DECL_NSIDOCSHELLTREEITEM
     NS_DECL_NSIDOCSHELLTREENODE
     NS_DECL_NSIDOCSHELLHISTORY
@@ -219,27 +244,48 @@ public:
     NS_DECL_NSIREFRESHURI
     NS_DECL_NSICONTENTVIEWERCONTAINER
     NS_DECL_NSIEDITORDOCSHELL
     NS_DECL_NSIWEBPAGEDESCRIPTOR
     NS_DECL_NSIAUTHPROMPTPROVIDER
     NS_DECL_NSIOBSERVER
     NS_DECL_NSILOADCONTEXT
     NS_DECL_NSIDOCSHELL_MOZILLA_1_9_1
+    NS_DECL_NSICLIPBOARDCOMMANDS
+    NS_DECL_NSIWEBSHELLSERVICES
 
     NS_IMETHOD Stop() {
         // Need this here because otherwise nsIWebNavigation::Stop
         // overrides the docloader's Stop()
         return nsDocLoader::Stop();
     }
 
     // Need to implement (and forward) nsISecurityEventSink, because
     // nsIWebProgressListener has methods with identical names...
     NS_FORWARD_NSISECURITYEVENTSINK(nsDocLoader::)
 
+    // nsILinkHandler
+    NS_IMETHOD OnLinkClick(nsIContent* aContent,
+        nsIURI* aURI,
+        const PRUnichar* aTargetSpec,
+        nsIInputStream* aPostDataStream = 0,
+        nsIInputStream* aHeadersDataStream = 0);
+    NS_IMETHOD OnLinkClickSync(nsIContent* aContent,
+        nsIURI* aURI,
+        const PRUnichar* aTargetSpec,
+        nsIInputStream* aPostDataStream = 0,
+        nsIInputStream* aHeadersDataStream = 0,
+        nsIDocShell** aDocShell = 0,
+        nsIRequest** aRequest = 0);
+    NS_IMETHOD OnOverLink(nsIContent* aContent,
+        nsIURI* aURI,
+        const PRUnichar* aTargetSpec);
+    NS_IMETHOD OnLeaveLink();
+    NS_IMETHOD GetLinkState(nsIURI* aLinkURI, nsLinkState& aState);
+
     nsDocShellInfoLoadType ConvertLoadTypeToDocShellLoadInfo(PRUint32 aLoadType);
     PRUint32 ConvertDocShellLoadInfoToLoadType(nsDocShellInfoLoadType aDocShellLoadType);
 
     // nsIScriptGlobalObjectOwner methods
     virtual nsIScriptGlobalObject* GetScriptGlobalObject();
 
     // Restores a cached presentation from history (mLSHE).
     // This method swaps out the content viewer and simulates loads for
@@ -248,16 +294,18 @@ public:
 
     // Perform a URI load from a refresh timer.  This is just like the
     // ForceRefreshURI method on nsIRefreshURI, but makes sure to take
     // the timer involved out of mRefreshURIList if it's there.
     // aTimer must not be null.
     nsresult ForceRefreshURIFromTimer(nsIURI * aURI, PRInt32 aDelay,
                                       PRBool aMetaRefresh, nsITimer* aTimer);
 
+    friend class OnLinkClickEvent;
+
 protected:
     // Object Management
     virtual ~nsDocShell();
     virtual void DestroyChildren();
 
     // Content Viewer Management
     NS_IMETHOD EnsureContentViewer();
     // aPrincipal can be passed in if the caller wants.  If null is
@@ -554,16 +602,24 @@ protected:
     // we are it's still OK to load this URI.
     PRBool IsOKToLoadURI(nsIURI* aURI);
     
     void ReattachEditorToWindow(nsISHEntry *aSHEntry);
 
     nsresult GetSessionStorageForURI(nsIURI* aURI,
                                      PRBool create,
                                      nsIDOMStorage** aStorage);
+
+    // helpers for executing commands
+    nsresult GetControllerForCommand(const char *inCommand,
+                                     nsIController** outController);
+    nsresult IsCommandEnabled(const char * inCommand, PRBool* outEnabled);
+    nsresult DoCommand(const char * inCommand);
+    nsresult EnsureCommandHandler();
+    
 protected:
     // Override the parent setter from nsDocLoader
     virtual nsresult SetDocLoaderParent(nsDocLoader * aLoader);
 
     // Event type dispatched by RestorePresentation
     class RestorePresentationEvent : public nsRunnable {
     public:
         NS_DECL_NSIRUNNABLE
@@ -698,22 +754,31 @@ protected:
 
     // WEAK REFERENCES BELOW HERE.
     // Note these are intentionally not addrefd.  Doing so will create a cycle.
     // For that reasons don't use nsCOMPtr.
 
     nsIDocShellTreeOwner *     mTreeOwner; // Weak Reference
     nsPIDOMEventTarget *       mChromeEventHandler; //Weak Reference
 
+    eCharsetReloadState mCharsetReloadState;
+    nsCOMPtr<nsICommandManager> mCommandManager;
+
 #ifdef DEBUG
     PRBool mInEnsureScriptEnv;
 #endif
 
     static nsIURIFixup *sURIFixup;
 
+#ifdef DEBUG
+private:
+    // We're counting the number of |nsDocShells| to help find leaks
+    static unsigned long gNumberOfDocShells;
+#endif /* DEBUG */
+
 public:
     class InterfaceRequestorProxy : public nsIInterfaceRequestor {
     public:
         InterfaceRequestorProxy(nsIInterfaceRequestor* p);
         virtual ~InterfaceRequestorProxy();
         NS_DECL_ISUPPORTS
         NS_DECL_NSIINTERFACEREQUESTOR
  
--- a/docshell/base/nsIDocShell.idl
+++ b/docshell/base/nsIDocShell.idl
@@ -292,22 +292,28 @@ interface nsIDocShell : nsISupports
    * not supporting zoom.  Implementations not supporting zoom should return
    * 1.0 all the time for the Get operation.  1.0 by the way is the default
    * of zoom.  This means 100% of normal scaling or in other words normal size
    * no zoom. 
    */
   attribute float zoom;
 
   /*
-   * XXX Comment here!
+   * The size, in CSS pixels, of the horizontal margins for the <body> of an
+   * HTML document in this docshel; used to implement the marginwidth attribute
+   * on HTML <frame>/<iframe> elements.  A value smaller than zero indicates
+   * that the attribute was not set.
    */
   attribute long marginWidth;
 
   /*
-   * XXX Comment here!
+   * The size, in CSS pixels, of the vertical margins for the <body> of an HTML
+   * document in this docshel; used to implement the marginheight attribute on
+   * HTML <frame>/<iframe> elements.  A value smaller than zero indicates that
+   * the attribute was not set.
    */
   attribute long marginHeight;
 
   /*
    * Tells the DocShell that it now has focus or has lost focus
    */
   attribute boolean hasFocus;
 
deleted file mode 100644
--- a/docshell/base/nsWebShell.cpp
+++ /dev/null
@@ -1,1450 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim:set ts=2 sw=2 sts=2 cin et: */
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is Mozilla Communicator client code.
- *
- * The Initial Developer of the Original Code is
- * Netscape Communications Corporation.
- * Portions created by the Initial Developer are Copyright (C) 1998
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *   Travis Bogard <travis@netscape.com>
- *   Dan Rosen <dr@netscape.com>
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either of the GNU General Public License Version 2 or later (the "GPL"),
- * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-#include "nsDocShell.h"
-#include "nsWebShell.h"
-#include "nsIWebBrowserChrome2.h"
-#include "nsIInterfaceRequestor.h"
-#include "nsIInterfaceRequestorUtils.h"
-#include "nsIWebProgress.h"
-#include "nsIContentViewer.h"
-#include "nsIDocumentViewer.h"
-#include "nsIMarkupDocumentViewer.h"
-#include "nsIClipboardCommands.h"
-#include "nsILinkHandler.h"
-#include "nsIStreamListener.h"
-#include "nsIPrompt.h"
-#include "nsNetUtil.h"
-#include "nsIRefreshURI.h"
-#include "nsIDOMEvent.h"
-#include "nsPresContext.h"
-#include "nsIComponentManager.h"
-#include "nsCRT.h"
-#include "nsString.h"
-#include "nsReadableUtils.h"
-#include "prprf.h"
-#include "nsIPluginHost.h"
-#include "nsplugin.h"
-#include "nsIPluginManager.h"
-#include "nsCDefaultURIFixup.h"
-#include "nsIContent.h"
-#include "prlog.h"
-#include "nsCOMPtr.h"
-#include "nsIPresShell.h"
-#include "nsIWebShellServices.h"
-#include "nsIGlobalHistory.h"
-#include "prmem.h"
-#include "prthread.h"
-#include "nsXPIDLString.h"
-#include "nsDOMError.h"
-#include "nsIDOMRange.h"
-#include "nsIURIContentListener.h"
-#include "nsIDOMDocument.h"
-#include "nsIDOMHTMLAnchorElement.h"
-#include "nsIBaseWindow.h"
-#include "nsIDocShell.h"
-#include "nsIDocShellTreeItem.h"
-#include "nsIDocShellTreeNode.h"
-#include "nsIDocShellTreeOwner.h"
-#include "nsCURILoader.h"
-#include "nsURILoader.h"
-#include "nsIDOMWindowInternal.h"
-#include "nsEscape.h"
-#include "nsIPlatformCharset.h"
-#include "nsICharsetConverterManager.h"
-#include "nsISocketTransportService.h"
-#include "nsTextFormatter.h"
-#include "nsPIDOMWindow.h"
-#include "nsPICommandUpdater.h"
-#include "nsIController.h"
-#include "nsIFocusController.h"
-#include "nsGUIEvent.h"
-#include "nsISHistoryInternal.h"
-
-#include "nsIHttpChannel.h"
-#include "nsIHttpChannelInternal.h"
-#include "nsIUploadChannel.h"
-#include "nsISeekableStream.h"
-#include "nsStreamUtils.h"
-#include "nsThreadUtils.h"
-
-#include "nsILocaleService.h"
-#include "nsIStringBundle.h"
-
-#include "nsICachingChannel.h"
-
-#include "nsIDocument.h"
-#include "nsITextToSubURI.h"
-
-#include "nsIExternalProtocolService.h"
-#include "nsCExternalHandlerService.h"
-
-#include "nsIIDNService.h"
-
-#include "nsIPrefBranch.h"
-#include "nsIPrefService.h"
-#include "nsITimer.h"
-#include "nsIScriptSecurityManager.h"
-#include "nsContentPolicyUtils.h"
-
-#include "nsIURIClassifier.h"
-
-#ifdef NS_DEBUG
-/**
- * Note: the log module is created during initialization which
- * means that you cannot perform logging before then.
- */
-static PRLogModuleInfo* gLogModule = PR_NewLogModule("webshell");
-#endif
-
-#define WEB_TRACE_CALLS        0x1
-#define WEB_TRACE_HISTORY      0x2
-
-#define WEB_LOG_TEST(_lm,_bit) (PRIntn((_lm)->level) & (_bit))
-
-#ifdef NS_DEBUG
-#define WEB_TRACE(_bit,_args)            \
-  PR_BEGIN_MACRO                         \
-    if (WEB_LOG_TEST(gLogModule,_bit)) { \
-      PR_LogPrint _args;                 \
-    }                                    \
-  PR_END_MACRO
-#else
-#define WEB_TRACE(_bit,_args)
-#endif
-
-//-----------------------------------------------------------------------------
-
-#define PREF_PINGS_ENABLED           "browser.send_pings"
-#define PREF_PINGS_MAX_PER_LINK      "browser.send_pings.max_per_link"
-#define PREF_PINGS_REQUIRE_SAME_HOST "browser.send_pings.require_same_host"
-
-// Check prefs to see if pings are enabled and if so what restrictions might
-// be applied.
-//
-// @param maxPerLink
-//   This parameter returns the number of pings that are allowed per link click
-//
-// @param requireSameHost
-//   This parameter returns PR_TRUE if pings are restricted to the same host as
-//   the document in which the click occurs.  If the same host restriction is
-//   imposed, then we still allow for pings to cross over to different
-//   protocols and ports for flexibility and because it is not possible to send
-//   a ping via FTP.
-//
-// @returns
-//   PR_TRUE if pings are enabled and PR_FALSE otherwise.
-//
-static PRBool
-PingsEnabled(PRInt32 *maxPerLink, PRBool *requireSameHost)
-{
-  PRBool allow = PR_FALSE;
-
-  *maxPerLink = 1;
-  *requireSameHost = PR_TRUE;
-
-  nsCOMPtr<nsIPrefBranch> prefs =
-      do_GetService(NS_PREFSERVICE_CONTRACTID);
-  if (prefs) {
-    PRBool val;
-    if (NS_SUCCEEDED(prefs->GetBoolPref(PREF_PINGS_ENABLED, &val)))
-      allow = val;
-    if (allow) {
-      prefs->GetIntPref(PREF_PINGS_MAX_PER_LINK, maxPerLink);
-      prefs->GetBoolPref(PREF_PINGS_REQUIRE_SAME_HOST, requireSameHost);
-    }
-  }
-
-  return allow;
-}
-
-static PRBool
-CheckPingURI(nsIURI* uri, nsIContent* content)
-{
-  if (!uri)
-    return PR_FALSE;
-
-  // Check with nsIScriptSecurityManager
-  nsCOMPtr<nsIScriptSecurityManager> ssmgr =
-    do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID);
-  NS_ENSURE_TRUE(ssmgr, PR_FALSE);
-
-  nsresult rv =
-    ssmgr->CheckLoadURIWithPrincipal(content->NodePrincipal(), uri,
-                                     nsIScriptSecurityManager::STANDARD);
-  if (NS_FAILED(rv)) {
-    return PR_FALSE;
-  }
-
-  // Ignore non-HTTP(S)
-  PRBool match;
-  if ((NS_FAILED(uri->SchemeIs("http", &match)) || !match) &&
-      (NS_FAILED(uri->SchemeIs("https", &match)) || !match)) {
-    return PR_FALSE;
-  }
-
-  // Check with contentpolicy
-  PRInt16 shouldLoad = nsIContentPolicy::ACCEPT;
-  rv = NS_CheckContentLoadPolicy(nsIContentPolicy::TYPE_PING,
-                                 uri,
-                                 content->NodePrincipal(),
-                                 content,
-                                 EmptyCString(), // mime hint
-                                 nsnull, //extra
-                                 &shouldLoad);
-  return NS_SUCCEEDED(rv) && NS_CP_ACCEPTED(shouldLoad);
-}
-
-typedef void (* ForEachPingCallback)(void *closure, nsIContent *content,
-                                     nsIURI *uri, nsIIOService *ios);
-
-static void
-ForEachPing(nsIContent *content, ForEachPingCallback callback, void *closure)
-{
-  // NOTE: Using nsIDOMNSHTMLAnchorElement2::GetPing isn't really worth it here
-  //       since we'd still need to parse the resulting string.  Instead, we
-  //       just parse the raw attribute.  It might be nice if the content node
-  //       implemented an interface that exposed an enumeration of nsIURIs.
-
-  // Make sure we are dealing with either an <A> or <AREA> element in the HTML
-  // or XHTML namespace.
-  if (!content->IsNodeOfType(nsINode::eHTML))
-    return;
-  nsIAtom *nameAtom = content->Tag();
-  if (!nameAtom->EqualsUTF8(NS_LITERAL_CSTRING("a")) &&
-      !nameAtom->EqualsUTF8(NS_LITERAL_CSTRING("area")))
-    return;
-
-  nsCOMPtr<nsIAtom> pingAtom = do_GetAtom("ping");
-  if (!pingAtom)
-    return;
-
-  nsAutoString value;
-  content->GetAttr(kNameSpaceID_None, pingAtom, value);
-  if (value.IsEmpty())
-    return;
-
-  nsCOMPtr<nsIIOService> ios = do_GetIOService();
-  if (!ios)
-    return;
-
-  nsIDocument *doc = content->GetOwnerDoc();
-  if (!doc)
-    return;
-
-  // value contains relative URIs split on spaces (U+0020)
-  const PRUnichar *start = value.BeginReading();
-  const PRUnichar *end   = value.EndReading();
-  const PRUnichar *iter  = start;
-  for (;;) {
-    if (iter < end && *iter != ' ') {
-      ++iter;
-    } else {  // iter is pointing at either end or a space
-      while (*start == ' ' && start < iter)
-        ++start;
-      if (iter != start) {
-        nsCOMPtr<nsIURI> uri, baseURI = content->GetBaseURI();
-        ios->NewURI(NS_ConvertUTF16toUTF8(Substring(start, iter)),
-                    doc->GetDocumentCharacterSet().get(),
-                    baseURI, getter_AddRefs(uri));
-        if (CheckPingURI(uri, content)) {
-          callback(closure, content, uri, ios);
-        }
-      }
-      start = iter = iter + 1;
-      if (iter >= end)
-        break;
-    }
-  }
-}
-
-//----------------------------------------------------------------------
-
-// We wait this many milliseconds before killing the ping channel...
-#define PING_TIMEOUT 10000
-
-static void
-OnPingTimeout(nsITimer *timer, void *closure)
-{
-  nsILoadGroup *loadGroup = static_cast<nsILoadGroup *>(closure);
-  loadGroup->Cancel(NS_ERROR_ABORT);
-  loadGroup->Release();
-}
-
-// Check to see if two URIs have the same host or not
-static PRBool
-IsSameHost(nsIURI *uri1, nsIURI *uri2)
-{
-  nsCAutoString host1, host2;
-  uri1->GetAsciiHost(host1);
-  uri2->GetAsciiHost(host2);
-  return host1.Equals(host2);
-}
-
-class nsPingListener : public nsIStreamListener
-                     , public nsIInterfaceRequestor
-                     , public nsIChannelEventSink
-{
-public:
-  NS_DECL_ISUPPORTS
-  NS_DECL_NSIREQUESTOBSERVER
-  NS_DECL_NSISTREAMLISTENER
-  NS_DECL_NSIINTERFACEREQUESTOR
-  NS_DECL_NSICHANNELEVENTSINK
-
-  nsPingListener(PRBool requireSameHost, nsIContent* content)
-    : mRequireSameHost(requireSameHost),
-      mContent(content)
-  {}
-
-private:
-  PRBool mRequireSameHost;
-  nsCOMPtr<nsIContent> mContent;
-};
-
-NS_IMPL_ISUPPORTS4(nsPingListener, nsIStreamListener, nsIRequestObserver,
-                   nsIInterfaceRequestor, nsIChannelEventSink)
-
-NS_IMETHODIMP
-nsPingListener::OnStartRequest(nsIRequest *request, nsISupports *context)
-{
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsPingListener::OnDataAvailable(nsIRequest *request, nsISupports *context,
-                                nsIInputStream *stream, PRUint32 offset,
-                                PRUint32 count)
-{
-  PRUint32 result;
-  return stream->ReadSegments(NS_DiscardSegment, nsnull, count, &result);
-}
-
-NS_IMETHODIMP
-nsPingListener::OnStopRequest(nsIRequest *request, nsISupports *context,
-                              nsresult status)
-{
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsPingListener::GetInterface(const nsIID &iid, void **result)
-{
-  if (iid.Equals(NS_GET_IID(nsIChannelEventSink))) {
-    NS_ADDREF_THIS();
-    *result = (nsIChannelEventSink *) this;
-    return NS_OK;
-  }
-
-  return NS_ERROR_NO_INTERFACE;
-}
-
-NS_IMETHODIMP
-nsPingListener::OnChannelRedirect(nsIChannel *oldChan, nsIChannel *newChan,
-                                  PRUint32 flags)
-{
-  nsCOMPtr<nsIURI> newURI;
-  newChan->GetURI(getter_AddRefs(newURI));
-
-  if (!CheckPingURI(newURI, mContent))
-    return NS_ERROR_ABORT;
-
-  if (!mRequireSameHost)
-    return NS_OK;
-
-  // XXXbz should this be using something more like the nsContentUtils
-  // same-origin checker?
-  nsCOMPtr<nsIURI> oldURI;
-  oldChan->GetURI(getter_AddRefs(oldURI));
-  NS_ENSURE_STATE(oldURI && newURI);
-
-  if (!IsSameHost(oldURI, newURI))
-    return NS_ERROR_ABORT;
-
-  return NS_OK;
-}
-
-struct SendPingInfo {
-  PRInt32 numPings;
-  PRInt32 maxPings;
-  PRBool  requireSameHost;
-  nsIURI *referrer;
-};
-
-static void
-SendPing(void *closure, nsIContent *content, nsIURI *uri, nsIIOService *ios)
-{
-  SendPingInfo *info = static_cast<SendPingInfo *>(closure);
-  if (info->numPings >= info->maxPings)
-    return;
-
-  if (info->requireSameHost) {
-    // Make sure the referrer and the given uri share the same origin.  We
-    // only require the same hostname.  The scheme and port may differ.
-    if (!IsSameHost(uri, info->referrer))
-      return;
-  }
-
-  nsIDocument *doc = content->GetOwnerDoc();
-  if (!doc)
-    return;
-
-  nsCOMPtr<nsIChannel> chan;
-  ios->NewChannelFromURI(uri, getter_AddRefs(chan));
-  if (!chan)
-    return;
-
-  // Don't bother caching the result of this URI load.
-  chan->SetLoadFlags(nsIRequest::INHIBIT_CACHING);
-
-  nsCOMPtr<nsIHttpChannel> httpChan = do_QueryInterface(chan);
-  if (!httpChan)
-    return;
-
-  // This is needed in order for 3rd-party cookie blocking to work.
-  nsCOMPtr<nsIHttpChannelInternal> httpInternal = do_QueryInterface(httpChan);
-  if (httpInternal)
-    httpInternal->SetDocumentURI(doc->GetDocumentURI());
-
-  if (info->referrer)
-    httpChan->SetReferrer(info->referrer);
-
-  httpChan->SetRequestMethod(NS_LITERAL_CSTRING("POST"));
-
-  // Remove extraneous request headers (to reduce request size)
-  httpChan->SetRequestHeader(NS_LITERAL_CSTRING("accept"),
-                             EmptyCString(), PR_FALSE);
-  httpChan->SetRequestHeader(NS_LITERAL_CSTRING("accept-language"),
-                             EmptyCString(), PR_FALSE);
-  httpChan->SetRequestHeader(NS_LITERAL_CSTRING("accept-charset"),
-                             EmptyCString(), PR_FALSE);
-  httpChan->SetRequestHeader(NS_LITERAL_CSTRING("accept-encoding"),
-                             EmptyCString(), PR_FALSE);
-
-  nsCOMPtr<nsIUploadChannel> uploadChan = do_QueryInterface(httpChan);
-  if (!uploadChan)
-    return;
-
-  // To avoid sending an unnecessary Content-Type header, we encode the
-  // closing portion of the headers in the POST body.
-  NS_NAMED_LITERAL_CSTRING(uploadData, "Content-Length: 0\r\n\r\n");
-
-  nsCOMPtr<nsIInputStream> uploadStream;
-  NS_NewPostDataStream(getter_AddRefs(uploadStream), PR_FALSE,
-                       uploadData, 0);
-  if (!uploadStream)
-    return;
-
-  uploadChan->SetUploadStream(uploadStream, EmptyCString(), -1);
-
-  // The channel needs to have a loadgroup associated with it, so that we can
-  // cancel the channel and any redirected channels it may create.
-  nsCOMPtr<nsILoadGroup> loadGroup =
-      do_CreateInstance(NS_LOADGROUP_CONTRACTID);
-  if (!loadGroup)
-    return;
-  chan->SetLoadGroup(loadGroup);
-
-  // Construct a listener that merely discards any response.  If successful at
-  // opening the channel, then it is not necessary to hold a reference to the
-  // channel.  The networking subsystem will take care of that for us.
-  nsCOMPtr<nsIStreamListener> listener =
-      new nsPingListener(info->requireSameHost, content);
-  if (!listener)
-    return;
-
-  // Observe redirects as well:
-  nsCOMPtr<nsIInterfaceRequestor> callbacks = do_QueryInterface(listener);
-  NS_ASSERTION(callbacks, "oops");
-  loadGroup->SetNotificationCallbacks(callbacks);
-
-  chan->AsyncOpen(listener, nsnull);
-
-  // Even if AsyncOpen failed, we still count this as a successful ping.  It's
-  // possible that AsyncOpen may have failed after triggering some background
-  // process that may have written something to the network.
-  info->numPings++;
-
-  // Prevent ping requests from stalling and never being garbage collected...
-  nsCOMPtr<nsITimer> timer =
-      do_CreateInstance(NS_TIMER_CONTRACTID);
-  if (timer) {
-    nsresult rv = timer->InitWithFuncCallback(OnPingTimeout, loadGroup,
-                                              PING_TIMEOUT,
-                                              nsITimer::TYPE_ONE_SHOT);
-    if (NS_SUCCEEDED(rv)) {
-      // When the timer expires, the callback function will release this
-      // reference to the loadgroup.
-      static_cast<nsILoadGroup *>(loadGroup.get())->AddRef();
-      loadGroup = 0;
-    }
-  }
-  
-  // If we failed to setup the timer, then we should just cancel the channel
-  // because we won't be able to ensure that it goes away in a timely manner.
-  if (loadGroup)
-    chan->Cancel(NS_ERROR_ABORT);
-}
-
-// Spec: http://whatwg.org/specs/web-apps/current-work/#ping
-static void
-DispatchPings(nsIContent *content, nsIURI *referrer)
-{
-  SendPingInfo info;
-
-  if (!PingsEnabled(&info.maxPings, &info.requireSameHost))
-    return;
-  if (info.maxPings == 0)
-    return;
-
-  info.numPings = 0;
-  info.referrer = referrer;
-
-  ForEachPing(content, SendPing, &info);
-}
-
-//----------------------------------------------------------------------
-
-// Note: operator new zeros our memory
-nsWebShell::nsWebShell() : nsDocShell()
-{
-#ifdef DEBUG
-  // We're counting the number of |nsWebShells| to help find leaks
-  ++gNumberOfWebShells;
-#endif
-#ifdef DEBUG
-    printf("++WEBSHELL %p == %ld\n", (void*) this, gNumberOfWebShells);
-#endif
-
-  InitFrameData();
-  mItemType = typeContent;
-  mCharsetReloadState = eCharsetReloadInit;
-}
-
-nsWebShell::~nsWebShell()
-{
-   Destroy();
-
-  ++mRefCnt; // following releases can cause this destructor to be called
-             // recursively if the refcount is allowed to remain 0
-
-  mContentViewer=nsnull;
-
-  InitFrameData();
-
-#ifdef DEBUG
-  // We're counting the number of |nsWebShells| to help find leaks
-  --gNumberOfWebShells;
-#endif
-#ifdef DEBUG
-  printf("--WEBSHELL %p == %ld\n", (void*) this, gNumberOfWebShells);
-#endif
-}
-
-void nsWebShell::InitFrameData()
-{
-  SetMarginWidth(-1);    
-  SetMarginHeight(-1);
-}
-
-nsresult
-nsWebShell::EnsureCommandHandler()
-{
-  if (!mCommandManager)
-  {
-    nsCOMPtr<nsPICommandUpdater> commandUpdater =
-      do_CreateInstance("@mozilla.org/embedcomp/command-manager;1");
-    if (!commandUpdater) return NS_ERROR_OUT_OF_MEMORY;
-    
-    nsCOMPtr<nsIDOMWindow> domWindow =
-      do_GetInterface(static_cast<nsIInterfaceRequestor *>(this));
-
-    nsresult rv = commandUpdater->Init(domWindow);
-    if (NS_SUCCEEDED(rv))
-      mCommandManager = do_QueryInterface(commandUpdater);
-  }
-  
-  return mCommandManager ? NS_OK : NS_ERROR_FAILURE;
-}
-
-
-
-NS_IMPL_ADDREF_INHERITED(nsWebShell, nsDocShell)
-NS_IMPL_RELEASE_INHERITED(nsWebShell, nsDocShell)
-
-NS_INTERFACE_MAP_BEGIN(nsWebShell)
-   NS_INTERFACE_MAP_ENTRY(nsIWebShellServices)
-   NS_INTERFACE_MAP_ENTRY(nsILinkHandler)
-   NS_INTERFACE_MAP_ENTRY(nsIClipboardCommands)
-NS_INTERFACE_MAP_END_INHERITING(nsDocShell)
-
-NS_IMETHODIMP
-nsWebShell::GetInterface(const nsIID &aIID, void** aInstancePtr)
-{
-   NS_PRECONDITION(aInstancePtr, "null out param");
-
-   *aInstancePtr = nsnull;
-
-   if(aIID.Equals(NS_GET_IID(nsICommandManager)))
-      {
-      NS_ENSURE_SUCCESS(EnsureCommandHandler(), NS_ERROR_FAILURE);
-      *aInstancePtr = mCommandManager;
-      NS_ADDREF((nsISupports*) *aInstancePtr);
-      return NS_OK;
-      }
-
-   return nsDocShell::GetInterface(aIID, aInstancePtr);
-}
-
-nsEventStatus
-nsWebShell::HandleEvent(nsGUIEvent *aEvent)
-{
-  return nsEventStatus_eIgnore;
-}
-
-
-//----------------------------------------------------------------------
-// Web Shell Services API
-
-//This functions is only called when a new charset is detected in loading a document. 
-//Its name should be changed to "CharsetReloadDocument"
-NS_IMETHODIMP
-nsWebShell::ReloadDocument(const char* aCharset,
-                           PRInt32 aSource)
-{
-
-  // XXX hack. kee the aCharset and aSource wait to pick it up
-  nsCOMPtr<nsIContentViewer> cv;
-  NS_ENSURE_SUCCESS(GetContentViewer(getter_AddRefs(cv)), NS_ERROR_FAILURE);
-  if (cv)
-  {
-    nsCOMPtr<nsIMarkupDocumentViewer> muDV = do_QueryInterface(cv);  
-    if (muDV)
-    {
-      PRInt32 hint;
-      muDV->GetHintCharacterSetSource(&hint);
-      if( aSource > hint ) 
-      {
-         muDV->SetHintCharacterSet(nsDependentCString(aCharset));
-         muDV->SetHintCharacterSetSource(aSource);
-         if(eCharsetReloadRequested != mCharsetReloadState) 
-         {
-            mCharsetReloadState = eCharsetReloadRequested;
-            return Reload(LOAD_FLAGS_CHARSET_CHANGE);
-         }
-      }
-    }
-  }
-  //return failer if this request is not accepted due to mCharsetReloadState
-  return NS_ERROR_WEBSHELL_REQUEST_REJECTED;
-}
-
-
-NS_IMETHODIMP
-nsWebShell::StopDocumentLoad(void)
-{
-  if(eCharsetReloadRequested != mCharsetReloadState) 
-  {
-    Stop(nsIWebNavigation::STOP_ALL);
-    return NS_OK;
-  }
-  //return failer if this request is not accepted due to mCharsetReloadState
-  return NS_ERROR_WEBSHELL_REQUEST_REJECTED;
-}
-
-NS_IMETHODIMP
-nsWebShell::SetRendering(PRBool aRender)
-{
-  if(eCharsetReloadRequested != mCharsetReloadState) 
-  {
-    if (mContentViewer) {
-       mContentViewer->SetEnableRendering(aRender);
-       return NS_OK;
-    }
-  }
-  //return failer if this request is not accepted due to mCharsetReloadState
-  return NS_ERROR_WEBSHELL_REQUEST_REJECTED;
-}
-
-//----------------------------------------------------------------------
-
-// WebShell link handling
-
-class OnLinkClickEvent : public nsRunnable {
-public:
-  OnLinkClickEvent(nsWebShell* aHandler, nsIContent* aContent,
-                   nsIURI* aURI,
-                   const PRUnichar* aTargetSpec,
-                   nsIInputStream* aPostDataStream = 0, 
-                   nsIInputStream* aHeadersDataStream = 0);
-
-  NS_IMETHOD Run() {
-    nsCOMPtr<nsPIDOMWindow> window(do_QueryInterface(mHandler->mScriptGlobal));
-    nsAutoPopupStatePusher popupStatePusher(window, mPopupState);
-
-    mHandler->OnLinkClickSync(mContent, mURI,
-                              mTargetSpec.get(), mPostDataStream,
-                              mHeadersDataStream,
-                              nsnull, nsnull);
-    return NS_OK;
-  }
-
-private:
-  nsRefPtr<nsWebShell>     mHandler;
-  nsCOMPtr<nsIURI>         mURI;
-  nsString                 mTargetSpec;
-  nsCOMPtr<nsIInputStream> mPostDataStream;
-  nsCOMPtr<nsIInputStream> mHeadersDataStream;
-  nsCOMPtr<nsIContent>     mContent;
-  PopupControlState        mPopupState;
-};
-
-OnLinkClickEvent::OnLinkClickEvent(nsWebShell* aHandler,
-                                   nsIContent *aContent,
-                                   nsIURI* aURI,
-                                   const PRUnichar* aTargetSpec,
-                                   nsIInputStream* aPostDataStream,
-                                   nsIInputStream* aHeadersDataStream)
-  : mHandler(aHandler)
-  , mURI(aURI)
-  , mTargetSpec(aTargetSpec)
-  , mPostDataStream(aPostDataStream)
-  , mHeadersDataStream(aHeadersDataStream)
-  , mContent(aContent)
-{
-  nsCOMPtr<nsPIDOMWindow> window(do_QueryInterface(mHandler->mScriptGlobal));
-
-  mPopupState = window->GetPopupControlState();
-}
-
-//----------------------------------------
-
-NS_IMETHODIMP
-nsWebShell::OnLinkClick(nsIContent* aContent,
-                        nsIURI* aURI,
-                        const PRUnichar* aTargetSpec,
-                        nsIInputStream* aPostDataStream,
-                        nsIInputStream* aHeadersDataStream)
-{
-  NS_ASSERTION(NS_IsMainThread(), "wrong thread");
-
-  if (!IsOKToLoadURI(aURI)) {
-    return NS_OK;
-  }
-
-  if (aContent->IsEditable()) {
-    return NS_OK;
-  }
-
-  nsCOMPtr<nsIRunnable> ev =
-      new OnLinkClickEvent(this, aContent, aURI, aTargetSpec,
-                           aPostDataStream, aHeadersDataStream);
-  return NS_DispatchToCurrentThread(ev);
-}
-
-NS_IMETHODIMP
-nsWebShell::OnLinkClickSync(nsIContent *aContent,
-                            nsIURI* aURI,
-                            const PRUnichar* aTargetSpec,
-                            nsIInputStream* aPostDataStream,
-                            nsIInputStream* aHeadersDataStream,
-                            nsIDocShell** aDocShell,
-                            nsIRequest** aRequest)
-{
-  // Initialize the DocShell / Request
-  if (aDocShell) {
-    *aDocShell = nsnull;
-  }
-  if (aRequest) {
-    *aRequest = nsnull;
-  }
-
-  if (!IsOKToLoadURI(aURI)) {
-    return NS_OK;
-  }
-
-  if (aContent->IsEditable()) {
-    return NS_OK;
-  }
-
-  {
-    // defer to an external protocol handler if necessary...
-    nsCOMPtr<nsIExternalProtocolService> extProtService = do_GetService(NS_EXTERNALPROTOCOLSERVICE_CONTRACTID);
-    if (extProtService) {
-      nsCAutoString scheme;
-      aURI->GetScheme(scheme);
-      if (!scheme.IsEmpty()) {
-        // if the URL scheme does not correspond to an exposed protocol, then we
-        // need to hand this link click over to the external protocol handler.
-        PRBool isExposed;
-        nsresult rv = extProtService->IsExposedProtocol(scheme.get(), &isExposed);
-        if (NS_SUCCEEDED(rv) && !isExposed) {
-          return extProtService->LoadURI(aURI, this); 
-        }
-      }
-    }
-  }
-
-  // Get the owner document of the link that was clicked, this will be
-  // the document that the link is in, or the last document that the
-  // link was in. From that document, we'll get the URI to use as the
-  // referer, since the current URI in this webshell/docshell may be a
-  // new document that we're in the process of loading.
-  nsCOMPtr<nsIDocument> refererDoc = aContent->GetOwnerDoc();
-  NS_ENSURE_TRUE(refererDoc, NS_ERROR_UNEXPECTED);
-
-  nsCOMPtr<nsIURI> referer = refererDoc->GetDocumentURI();
-
-  // referer could be null here in some odd cases, but that's ok,
-  // we'll just load the link w/o sending a referer in those cases.
-
-  nsAutoString target(aTargetSpec);
-
-  // If this is an anchor element, grab its type property to use as a hint
-  nsAutoString typeHint;
-  nsCOMPtr<nsIDOMHTMLAnchorElement> anchor(do_QueryInterface(aContent));
-  if (anchor) {
-    anchor->GetType(typeHint);
-  }
-  
-  nsresult rv = InternalLoad(aURI,                      // New URI
-                             referer,                   // Referer URI
-                             aContent->NodePrincipal(), // Owner is our node's
-                                                        // principal
-                             INTERNAL_LOAD_FLAGS_NONE,
-                             target.get(),              // Window target
-                             NS_LossyConvertUTF16toASCII(typeHint).get(),
-                             aPostDataStream,           // Post data stream
-                             aHeadersDataStream,        // Headers stream
-                             LOAD_LINK,                 // Load type
-                             nsnull,                    // No SHEntry
-                             PR_TRUE,                   // first party site
-                             aDocShell,                 // DocShell out-param
-                             aRequest);                 // Request out-param
-  if (NS_SUCCEEDED(rv)) {
-    DispatchPings(aContent, referer);
-  }
-  return rv;
-}
-
-NS_IMETHODIMP
-nsWebShell::OnOverLink(nsIContent* aContent,
-                       nsIURI* aURI,
-                       const PRUnichar* aTargetSpec)
-{
-  if (aContent->IsEditable()) {
-    return NS_OK;
-  }
-
-  nsCOMPtr<nsIWebBrowserChrome2> browserChrome2 = do_GetInterface(mTreeOwner);
-  nsresult rv = NS_ERROR_FAILURE;
-
-  nsCOMPtr<nsIWebBrowserChrome> browserChrome;
-  if (!browserChrome2) {
-    browserChrome = do_GetInterface(mTreeOwner);
-    if (!browserChrome)
-      return rv;
-  }
-
-  nsCOMPtr<nsITextToSubURI> textToSubURI =
-      do_GetService(NS_ITEXTTOSUBURI_CONTRACTID, &rv);
-  if (NS_FAILED(rv))
-    return rv;
-
-  // use url origin charset to unescape the URL
-  nsCAutoString charset;
-  rv = aURI->GetOriginCharset(charset);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  nsCAutoString spec;
-  rv = aURI->GetSpec(spec);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  nsAutoString uStr;
-  rv = textToSubURI->UnEscapeURIForUI(charset, spec, uStr);    
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  if (browserChrome2) {
-    nsCOMPtr<nsIDOMElement> element = do_QueryInterface(aContent);
-    rv = browserChrome2->SetStatusWithContext(nsIWebBrowserChrome::STATUS_LINK,
-                                              uStr, element);
-  } else {
-    rv = browserChrome->SetStatus(nsIWebBrowserChrome::STATUS_LINK, uStr.get());
-  }
-  return rv;
-}
-
-NS_IMETHODIMP
-nsWebShell::OnLeaveLink()
-{
-  nsCOMPtr<nsIWebBrowserChrome> browserChrome(do_GetInterface(mTreeOwner));
-  nsresult rv = NS_ERROR_FAILURE;
-
-  if (browserChrome)  {
-      rv = browserChrome->SetStatus(nsIWebBrowserChrome::STATUS_LINK,
-                                    EmptyString().get());
-  }
-  return rv;
-}
-
-NS_IMETHODIMP
-nsWebShell::GetLinkState(nsIURI* aLinkURI, nsLinkState& aState)
-{
-  if (!aLinkURI) {
-    // No uri means not a link
-    aState = eLinkState_NotLink;
-    return NS_OK;
-  }
-    
-  aState = eLinkState_Unvisited;
-
-  // no history, leave state unchanged
-  if (!mGlobalHistory)
-    return NS_OK;
-
-  PRBool isVisited;
-  NS_ENSURE_SUCCESS(mGlobalHistory->IsVisited(aLinkURI, &isVisited),
-                    NS_ERROR_FAILURE);
-  if (isVisited)
-    aState = eLinkState_Visited;
-  
-  return NS_OK;
-}
-
-//----------------------------------------------------------------------
-nsresult nsWebShell::EndPageLoad(nsIWebProgress *aProgress,
-                                 nsIChannel* channel,
-                                 nsresult aStatus)
-{
-  nsresult rv = NS_OK;
-
-  if(!channel)
-    return NS_ERROR_NULL_POINTER;
-    
-  nsCOMPtr<nsIURI> url;
-  rv = channel->GetURI(getter_AddRefs(url));
-  if (NS_FAILED(rv)) return rv;
-  
-  // clean up reload state for meta charset
-  if(eCharsetReloadRequested == mCharsetReloadState)
-    mCharsetReloadState = eCharsetReloadStopOrigional;
-  else 
-    mCharsetReloadState = eCharsetReloadInit;
-
-  // Save a pointer to the currently-loading history entry.
-  // nsDocShell::EndPageLoad will clear mLSHE, but we may need this history
-  // entry further down in this method.
-  nsCOMPtr<nsISHEntry> loadingSHE = mLSHE;
-  
-  //
-  // one of many safeguards that prevent death and destruction if
-  // someone is so very very rude as to bring this window down
-  // during this load handler.
-  //
-  nsCOMPtr<nsIDocShell> kungFuDeathGrip(this);
-  nsDocShell::EndPageLoad(aProgress, channel, aStatus);
-
-  // Test if this is the top frame or a subframe
-  PRBool isTopFrame = PR_TRUE;
-  nsCOMPtr<nsIDocShellTreeItem> targetParentTreeItem;
-  rv = GetSameTypeParent(getter_AddRefs(targetParentTreeItem));
-  if (NS_SUCCEEDED(rv) && targetParentTreeItem) 
-  {
-    isTopFrame = PR_FALSE;
-  }
-
-  //
-  // If the page load failed, then deal with the error condition...
-  // Errors are handled as follows:
-  //   1. Check to see if it's a file not found error or bad content
-  //      encoding error.
-  //   2. Send the URI to a keyword server (if enabled)
-  //   3. If the error was DNS failure, then add www and .com to the URI
-  //      (if appropriate).
-  //   4. Throw an error dialog box...
-  //
-
-  if (url && NS_FAILED(aStatus))
-  {
-    if (aStatus == NS_ERROR_FILE_NOT_FOUND ||
-        aStatus == NS_ERROR_INVALID_CONTENT_ENCODING)
-    {
-      DisplayLoadError(aStatus, url, nsnull, channel);
-      return NS_OK;
-    }
-
-    if (sURIFixup)
-    {
-      //
-      // Try and make an alternative URI from the old one
-      //
-      nsCOMPtr<nsIURI> newURI;
-
-      nsCAutoString oldSpec;
-      url->GetSpec(oldSpec);
-      
-      //
-      // First try keyword fixup
-      //
-      if (aStatus == NS_ERROR_UNKNOWN_HOST && mAllowKeywordFixup)
-      {
-        PRBool keywordsEnabled = PR_FALSE;
-
-        if (mPrefs && NS_FAILED(mPrefs->GetBoolPref("keyword.enabled", &keywordsEnabled)))
-            keywordsEnabled = PR_FALSE;
-
-        nsCAutoString host;
-        url->GetHost(host);
-
-        nsCAutoString scheme;
-        url->GetScheme(scheme);
-
-        PRInt32 dotLoc = host.FindChar('.');
-
-        // we should only perform a keyword search under the following conditions:
-        // (0) Pref keyword.enabled is true
-        // (1) the url scheme is http (or https)
-        // (2) the url does not have a protocol scheme
-        // If we don't enforce such a policy, then we end up doing keyword searchs on urls
-        // we don't intend like imap, file, mailbox, etc. This could lead to a security
-        // problem where we send data to the keyword server that we shouldn't be. 
-        // Someone needs to clean up keywords in general so we can determine on a per url basis
-        // if we want keywords enabled...this is just a bandaid...
-        if (keywordsEnabled && !scheme.IsEmpty() &&
-           (scheme.Find("http") != 0)) {
-            keywordsEnabled = PR_FALSE;
-        }
-
-        if(keywordsEnabled && (kNotFound == dotLoc)) {
-          // only send non-qualified hosts to the keyword server
-          //
-          // If this string was passed through nsStandardURL by chance, then it
-          // may have been converted from UTF-8 to ACE, which would result in a
-          // completely bogus keyword query.  Here we try to recover the
-          // original Unicode value, but this is not 100% correct since the
-          // value may have been normalized per the IDN normalization rules.
-          //
-          // Since we don't have access to the exact original string that was
-          // entered by the user, this will just have to do.
-          //
-          PRBool isACE;
-          nsCAutoString utf8Host;
-          nsCOMPtr<nsIIDNService> idnSrv =
-              do_GetService(NS_IDNSERVICE_CONTRACTID);
-          if (idnSrv &&
-              NS_SUCCEEDED(idnSrv->IsACE(host, &isACE)) && isACE &&
-              NS_SUCCEEDED(idnSrv->ConvertACEtoUTF8(host, utf8Host)))
-            sURIFixup->KeywordToURI(utf8Host, getter_AddRefs(newURI));
-          else
-            sURIFixup->KeywordToURI(host, getter_AddRefs(newURI));
-        } // end keywordsEnabled
-      }
-
-      //
-      // Now try change the address, e.g. turn http://foo into http://www.foo.com
-      //
-      if (aStatus == NS_ERROR_UNKNOWN_HOST ||
-          aStatus == NS_ERROR_NET_RESET)
-      {
-        PRBool doCreateAlternate = PR_TRUE;
-        
-        // Skip fixup for anything except a normal document load operation on
-        // the topframe.
-        
-        if (mLoadType != LOAD_NORMAL || !isTopFrame)
-        {
-          doCreateAlternate = PR_FALSE;
-        }
-        else
-        {
-          // Test if keyword lookup produced a new URI or not
-          if (newURI)
-          {
-            PRBool sameURI = PR_FALSE;
-            url->Equals(newURI, &sameURI);
-            if (!sameURI)
-            {
-              // Keyword lookup made a new URI so no need to try an
-              // alternate one.
-              doCreateAlternate = PR_FALSE;
-            }
-          }
-        }
-        if (doCreateAlternate)
-        {
-          newURI = nsnull;
-          sURIFixup->CreateFixupURI(oldSpec,
-              nsIURIFixup::FIXUP_FLAGS_MAKE_ALTERNATE_URI, getter_AddRefs(newURI));
-        }
-      }
-
-      //
-      // Did we make a new URI that is different to the old one? If so load it.
-      //
-      if (newURI)
-      {
-        // Make sure the new URI is different from the old one, otherwise
-        // there's little point trying to load it again.
-        PRBool sameURI = PR_FALSE;
-        url->Equals(newURI, &sameURI);
-        if (!sameURI)
-        {
-          nsCAutoString newSpec;
-          newURI->GetSpec(newSpec);
-          NS_ConvertUTF8toUTF16 newSpecW(newSpec);
-
-          return LoadURI(newSpecW.get(),      // URI string
-                         LOAD_FLAGS_NONE, // Load flags
-                         nsnull,          // Referring URI
-                         nsnull,          // Post data stream
-                         nsnull);         // Headers stream
-        }
-      }
-    }
-
-    //
-    // Well, fixup didn't work :-(
-    // It is time to throw an error dialog box, and be done with it...
-    //
-
-    // Errors to be shown only on top-level frames
-    if ((aStatus == NS_ERROR_UNKNOWN_HOST || 
-         aStatus == NS_ERROR_CONNECTION_REFUSED ||
-         aStatus == NS_ERROR_UNKNOWN_PROXY_HOST || 
-         aStatus == NS_ERROR_PROXY_CONNECTION_REFUSED) &&
-            (isTopFrame || mUseErrorPages)) {
-      DisplayLoadError(aStatus, url, nsnull, channel);
-    }
-    // Errors to be shown for any frame
-    else if (aStatus == NS_ERROR_NET_TIMEOUT ||
-             aStatus == NS_ERROR_REDIRECT_LOOP ||
-             aStatus == NS_ERROR_UNKNOWN_SOCKET_TYPE ||
-             aStatus == NS_ERROR_NET_INTERRUPT ||
-             aStatus == NS_ERROR_NET_RESET ||
-             aStatus == NS_ERROR_MALWARE_URI ||
-             aStatus == NS_ERROR_PHISHING_URI ||
-             aStatus == NS_ERROR_UNSAFE_CONTENT_TYPE ||
-             NS_ERROR_GET_MODULE(aStatus) == NS_ERROR_MODULE_SECURITY) {
-      DisplayLoadError(aStatus, url, nsnull, channel);
-    }
-    else if (aStatus == NS_ERROR_DOCUMENT_NOT_CACHED) {
-      /* A document that was requested to be fetched *only* from
-       * the cache is not in cache. May be this is one of those 
-       * postdata results. Throw a  dialog to the user,
-       * saying that the page has expired from cache and ask if 
-       * they wish to refetch the page from the net. Do this only
-       * if the request is a form post.
-       */
-      nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(channel));
-      nsCAutoString method;
-      if (httpChannel)
-        httpChannel->GetRequestMethod(method);
-      if (method.Equals("POST") && !NS_IsOffline()) {
-        PRBool repost;
-        rv = ConfirmRepost(&repost);
-        if (NS_FAILED(rv)) return rv;
-        // If the user pressed cancel in the dialog, return. Don't try to load
-        // the page without the post data.
-        if (!repost)
-          return NS_OK;
-
-        // The user wants to repost the data to the server.
-        // If the page was loaded due to a back/forward/go
-        // operation, update the session history index.
-        // This is similar to the updating done in
-        // nsDocShell::OnNewURI() for regular pages
-        nsCOMPtr<nsISHistory> rootSH=mSessionHistory;
-        if (!mSessionHistory) {
-          nsCOMPtr<nsIDocShellTreeItem> root;
-          //Get the root docshell
-          GetSameTypeRootTreeItem(getter_AddRefs(root));
-          if (root) {
-            // QI root to nsIWebNavigation
-            nsCOMPtr<nsIWebNavigation> rootAsWebnav(do_QueryInterface(root));
-            if (rootAsWebnav) {
-            // Get the handle to SH from the root docshell
-            rootAsWebnav->GetSessionHistory(getter_AddRefs(rootSH));
-            }
-          }
-        }  // mSessionHistory
-
-        if (rootSH && (mLoadType & LOAD_CMD_HISTORY)) {
-          nsCOMPtr<nsISHistoryInternal> shInternal(do_QueryInterface(rootSH));
-          if (shInternal) {
-            rootSH->GetIndex(&mPreviousTransIndex);
-            shInternal->UpdateIndex();
-            rootSH->GetIndex(&mLoadedTransIndex);
-#ifdef DEBUG_PAGE_CACHE
-            printf("Previous index: %d, Loaded index: %d\n\n",
-                  mPreviousTransIndex, mLoadedTransIndex);
-#endif
-          }
-        }
-
-        // Make it look like we really did honestly finish loading the
-        // history page we were loading, since the "reload" load we're
-        // about to kick off will reload our current history entry.  This
-        // is a bit of a hack, and if the force-load fails I think we'll
-        // end up being confused about what page we're on... but we would
-        // anyway, since we've updated the session history index above.
-        SetHistoryEntry(&mOSHE, loadingSHE);
-
-        // The user does want to repost the data to the server.
-        // Initiate a new load again.
-
-        // Get the postdata if any from the channel.
-        nsCOMPtr<nsIInputStream> inputStream;
-        nsCOMPtr<nsIURI> referrer;
-        if (channel) {
-          nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(channel));
-
-          if(httpChannel) {
-            httpChannel->GetReferrer(getter_AddRefs(referrer));
-            nsCOMPtr<nsIUploadChannel> uploadChannel(do_QueryInterface(channel));
-            if (uploadChannel) {
-              uploadChannel->GetUploadStream(getter_AddRefs(inputStream));
-            }
-          }
-        }
-        nsCOMPtr<nsISeekableStream> postDataSeekable(do_QueryInterface(inputStream));
-        if (postDataSeekable)
-        {
-          postDataSeekable->Seek(nsISeekableStream::NS_SEEK_SET, 0);
-        }
-        InternalLoad(url,                               // URI
-                    referrer,                          // Referring URI
-                    nsnull,                            // Owner
-                    INTERNAL_LOAD_FLAGS_INHERIT_OWNER, // Inherit owner
-                    nsnull,                            // No window target
-                    nsnull,                            // No type hint
-                    inputStream,                       // Post data stream
-                    nsnull,                            // No headers stream
-                    LOAD_RELOAD_BYPASS_PROXY_AND_CACHE,// Load type
-                    nsnull,                            // No SHEntry
-                    PR_TRUE,                           // first party site
-                    nsnull,                            // No nsIDocShell
-                    nsnull);                           // No nsIRequest
-      }
-      else {
-        DisplayLoadError(aStatus, url, nsnull, channel);
-      }
-    }
-  } // if we have a host
-
-  return NS_OK;
-}
-
-//
-// Routines for selection and clipboard
-//
-
-#ifdef XP_MAC
-#pragma mark -
-#endif
-
-nsresult
-nsWebShell::GetControllerForCommand ( const char * inCommand, nsIController** outController )
-{
-  NS_ENSURE_ARG_POINTER(outController);
-  *outController = nsnull;
-  
-  nsresult rv = NS_ERROR_FAILURE;
-  
-  nsCOMPtr<nsPIDOMWindow> window ( do_QueryInterface(mScriptGlobal) );
-  if ( window ) {
-    nsIFocusController *focusController = window->GetRootFocusController();
-    if ( focusController )
-      rv = focusController->GetControllerForCommand ( inCommand, outController );
-  } // if window
-
-  return rv;
-  
-} // GetControllerForCommand
-
-
-nsresult
-nsWebShell::IsCommandEnabled ( const char * inCommand, PRBool* outEnabled )
-{
-  NS_ENSURE_ARG_POINTER(outEnabled);
-  *outEnabled = PR_FALSE;
-
-  nsresult rv = NS_ERROR_FAILURE;
-  
-  nsCOMPtr<nsIController> controller;
-  rv = GetControllerForCommand ( inCommand, getter_AddRefs(controller) );
-  if ( controller )
-    rv = controller->IsCommandEnabled(inCommand, outEnabled);
-  
-  return rv;
-}
-
-
-nsresult
-nsWebShell::DoCommand ( const char * inCommand )
-{
-  nsresult rv = NS_ERROR_FAILURE;
-  
-  nsCOMPtr<nsIController> controller;
-  rv = GetControllerForCommand ( inCommand, getter_AddRefs(controller) );
-  if ( controller )
-    rv = controller->DoCommand(inCommand);
-  
-  return rv;
-}
-
-
-NS_IMETHODIMP
-nsWebShell::CanCutSelection(PRBool* aResult)
-{
-  return IsCommandEnabled ( "cmd_cut", aResult );
-}
-
-NS_IMETHODIMP
-nsWebShell::CanCopySelection(PRBool* aResult)
-{
-  return IsCommandEnabled ( "cmd_copy", aResult );
-}
-
-NS_IMETHODIMP
-nsWebShell::CanCopyLinkLocation(PRBool* aResult)
-{
-  return IsCommandEnabled ( "cmd_copyLink", aResult );
-}
-
-NS_IMETHODIMP
-nsWebShell::CanCopyImageLocation(PRBool* aResult)
-{
-  return IsCommandEnabled ( "cmd_copyImageLocation",
-                            aResult );
-}
-
-NS_IMETHODIMP
-nsWebShell::CanCopyImageContents(PRBool* aResult)
-{
-  return IsCommandEnabled ( "cmd_copyImageContents",
-                            aResult );
-}
-
-NS_IMETHODIMP
-nsWebShell::CanPaste(PRBool* aResult)
-{
-  return IsCommandEnabled ( "cmd_paste", aResult );
-}
-
-NS_IMETHODIMP
-nsWebShell::CutSelection(void)
-{
-  return DoCommand ( "cmd_cut" );
-}
-
-NS_IMETHODIMP
-nsWebShell::CopySelection(void)
-{
-  return DoCommand ( "cmd_copy" );
-}
-
-NS_IMETHODIMP
-nsWebShell::CopyLinkLocation(void)
-{
-  return DoCommand ( "cmd_copyLink" );
-}
-
-NS_IMETHODIMP
-nsWebShell::CopyImageLocation(void)
-{
-  return DoCommand ( "cmd_copyImageLocation" );
-}
-
-NS_IMETHODIMP
-nsWebShell::CopyImageContents(void)
-{
-  return DoCommand ( "cmd_copyImageContents" );
-}
-
-NS_IMETHODIMP
-nsWebShell::Paste(void)
-{
-  return DoCommand ( "cmd_paste" );
-}
-
-NS_IMETHODIMP
-nsWebShell::SelectAll(void)
-{
-  return DoCommand ( "cmd_selectAll" );
-}
-
-
-//
-// SelectNone
-//
-// Collapses the current selection, insertion point ends up at beginning
-// of previous selection.
-//
-NS_IMETHODIMP
-nsWebShell::SelectNone(void)
-{
-  return DoCommand ( "cmd_selectNone" );
-}
-
-
-#ifdef XP_MAC
-#pragma mark -
-#endif
-
-//*****************************************************************************
-// nsWebShell::nsIBaseWindow
-//*****************************************************************************   
-
-NS_IMETHODIMP nsWebShell::Create()
-{
-  if (mPrefs) {
-    // We've already been created
-    return NS_OK;
-  }
-  
-  WEB_TRACE(WEB_TRACE_CALLS,
-            ("nsWebShell::Init: this=%p", this));
-
-  return nsDocShell::Create();
-}
-
-#ifdef DEBUG
-unsigned long nsWebShell::gNumberOfWebShells = 0;
-#endif
deleted file mode 100644
--- a/docshell/base/nsWebShell.h
+++ /dev/null
@@ -1,143 +0,0 @@
-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
- *
- * ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is the Mozilla browser.
- *
- * The Initial Developer of the Original Code is
- * Netscape Communications, Inc.
- * Portions created by the Initial Developer are Copyright (C) 1999
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either of the GNU General Public License Version 2 or later (the "GPL"),
- * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-#ifndef webshell____h
-#define webshell____h
-
-#include "nsError.h"
-#include "nsIWebShellServices.h"
-#include "nsILinkHandler.h"
-#include "nsIClipboardCommands.h"
-#include "nsDocShell.h"
-#include "nsICommandManager.h"
-#include "nsIIOService.h"
-#include "nsCRT.h"
-
-class nsIController;
-struct PRThread;
-class OnLinkClickEvent;
-
-typedef enum {
-    eCharsetReloadInit,
-    eCharsetReloadRequested,
-    eCharsetReloadStopOrigional
-} eCharsetReloadState;
-
-#define NS_ERROR_WEBSHELL_REQUEST_REJECTED  NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_GENERAL,1001)
-
-// Class ID for webshell
-#define NS_WEB_SHELL_CID \
- { 0xa6cf9059, 0x15b3, 0x11d2,{0x93, 0x2e, 0x00, 0x80, 0x5f, 0x8a, 0xdd, 0x32}}
-
-class nsWebShell : public nsDocShell,
-                   public nsIWebShellServices,
-                   public nsILinkHandler,
-                   public nsIClipboardCommands
-{
-public:
-    nsWebShell();
-    virtual ~nsWebShell();
-
-    NS_DECL_AND_IMPL_ZEROING_OPERATOR_NEW
-
-    NS_DECL_ISUPPORTS_INHERITED
-    NS_DECL_NSIINTERFACEREQUESTOR
-    NS_DECL_NSICLIPBOARDCOMMANDS
-    NS_DECL_NSIWEBSHELLSERVICES
-
-    // nsILinkHandler
-    NS_IMETHOD OnLinkClick(nsIContent* aContent,
-        nsIURI* aURI,
-        const PRUnichar* aTargetSpec,
-        nsIInputStream* aPostDataStream = 0,
-        nsIInputStream* aHeadersDataStream = 0);
-    NS_IMETHOD OnLinkClickSync(nsIContent* aContent,
-        nsIURI* aURI,
-        const PRUnichar* aTargetSpec,
-        nsIInputStream* aPostDataStream = 0,
-        nsIInputStream* aHeadersDataStream = 0,
-        nsIDocShell** aDocShell = 0,
-        nsIRequest** aRequest = 0);
-    NS_IMETHOD OnOverLink(nsIContent* aContent,
-        nsIURI* aURI,
-        const PRUnichar* aTargetSpec);
-    NS_IMETHOD OnLeaveLink();
-    NS_IMETHOD GetLinkState(nsIURI* aLinkURI, nsLinkState& aState);
-
-    NS_IMETHOD Create();
-
-    static nsEventStatus HandleEvent(nsGUIEvent *aEvent);
-
-    // NS_IMETHOD SetURL(const PRUnichar* aURL);
-
-    friend class OnLinkClickEvent;
-
-protected:
-    void InitFrameData();
-
-    // helpers for executing commands
-    virtual nsresult GetControllerForCommand ( const char *inCommand, nsIController** outController );
-    virtual nsresult IsCommandEnabled ( const char * inCommand, PRBool* outEnabled );
-    virtual nsresult DoCommand ( const char * inCommand );
-    nsresult EnsureCommandHandler();
-
-    //
-    // Helper method that is called when a new document (including any
-    // sub-documents - ie. frames) has been completely loaded.
-    //
-    virtual nsresult EndPageLoad(nsIWebProgress *aProgress,
-        nsIChannel* channel,
-        nsresult aStatus);
-
-    eCharsetReloadState mCharsetReloadState;
-
-    nsresult CreateViewer(nsIRequest* request,
-        const char* aContentType,
-        const char* aCommand,
-        nsIStreamListener** aResult);
-
-    nsCOMPtr<nsICommandManager> mCommandManager;
-    
-#ifdef DEBUG
-private:
-    // We're counting the number of |nsWebShells| to help find leaks
-    static unsigned long gNumberOfWebShells;
-#endif /* DEBUG */
-};
-
-#endif /* webshell____h */
-
--- a/docshell/build/nsDocShellCID.h
+++ b/docshell/build/nsDocShellCID.h
@@ -71,16 +71,29 @@
  * checking a channel load against the URI classifier service.
  */
 #define NS_CHANNELCLASSIFIER_CID \
  { 0xce02d538, 0x0217, 0x47a3,{0xa5, 0x89, 0xb5, 0x17, 0x90, 0xfd, 0xd8, 0xce}}
 
 #define NS_CHANNELCLASSIFIER_CONTRACTID "@mozilla.org/channelclassifier"
 
 /**
+ * Class and contract ID for the docshell.  This is the container for a web
+ * navigation context.  It implements too many interfaces to count, and the
+ * exact ones keep changing; if they stabilize somewhat that will get
+ * documented.
+ */
+#define NS_DOCSHELL_CID                                             \
+    { 0xf1eac762, 0x87e9, 0x11d3,                                   \
+      { 0xaf, 0x80, 0x00, 0xa0, 0x24, 0xff, 0xc0, 0x8c } }
+#define NS_DOCSHELL_CONTRACTID "@mozilla.org/docshell/html;1"
+
+
+
+/**
  * An observer service topic that can be listened to to catch creation
  * of content browsing areas (both toplevel ones and subframes).  The
  * subject of the notification will be the nsIWebNavigation being
  * created.  At this time the additional data wstring is not defined
  * to be anything in particular.
  */
 #define NS_WEBNAVIGATION_CREATE "webnavigation-create"
 
--- a/docshell/build/nsDocShellModule.cpp
+++ b/docshell/build/nsDocShellModule.cpp
@@ -37,17 +37,17 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsIModule.h"
 #include "nsIGenericFactory.h"
 
 #include "nsDocShellCID.h"
 
-#include "nsWebShell.h"
+#include "nsDocShell.h"
 #include "nsDefaultURIFixup.h"
 #include "nsWebNavigationInfo.h"
 
 #include "nsAboutRedirector.h"
 
 // uriloader
 #include "nsURILoader.h"
 #include "nsDocLoader.h"
@@ -95,17 +95,17 @@ Initialize(nsIModule* aSelf)
 static void
 Shutdown(nsIModule* aSelf)
 {
   nsSHEntry::Shutdown();
   gInitialized = PR_FALSE;
 }
 
 // docshell
-NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsWebShell, Init)
+NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsDocShell, Init)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsDefaultURIFixup)
 NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsWebNavigationInfo, Init)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsClassifierCallback)
 
 // uriloader
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsURILoader)
 NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsDocLoader, Init)
 NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsOSHelperAppService, Init)
@@ -127,29 +127,22 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(nsInterne
 // session history
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsSHEntry)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsSHTransaction)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsSHistory)
 
 // download history
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsDownloadHistory)
 
-// Currently no-one is instantiating docshell's directly because
-// nsWebShell is still our main "shell" class. nsWebShell is a subclass
-// of nsDocShell. Once migration is complete, docshells will be the main
-// "shell" class and this module will need to register the docshell as
-// a component
-//NS_GENERIC_FACTORY_CONSTRUCTOR(nsDocShell)
-
 static const nsModuleComponentInfo gDocShellModuleInfo[] = {
   // docshell
-    { "WebShell", 
-      NS_WEB_SHELL_CID,
-      "@mozilla.org/webshell;1",
-      nsWebShellConstructor
+    { "DocShell", 
+      NS_DOCSHELL_CID,
+      "@mozilla.org/docshell;1",
+      nsDocShellConstructor
     },
     { "Default keyword fixup", 
       NS_DEFAULTURIFIXUP_CID,
       NS_URIFIXUP_CONTRACTID,
       nsDefaultURIFixupConstructor
     },
     { "Webnavigation info service",
       NS_WEBNAVIGATION_INFO_CID,
--- a/editor/composer/src/nsEditingSession.cpp
+++ b/editor/composer/src/nsEditingSession.cpp
@@ -985,17 +985,17 @@ nsEditingSession::EndDocumentLoad(nsIWeb
   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 nsWebShell does (need to refactor).
+  // 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) {
--- a/editor/composer/src/nsEditorParserObserver.cpp
+++ b/editor/composer/src/nsEditorParserObserver.cpp
@@ -81,17 +81,17 @@ NS_IMETHODIMP nsEditorParserObserver::No
   if (eHTMLTag_frameset == aTag)
   {
     Notify();
     return NS_OK;
   }
   else
     return NS_ERROR_ILLEGAL_VALUE;
 }
-NS_IMETHODIMP nsEditorParserObserver::Notify(nsISupports* aWebShell, 
+NS_IMETHODIMP nsEditorParserObserver::Notify(nsISupports* aDocShell, 
                                              nsISupports* aChannel, 
                                              const PRUnichar* aTag, 
                                              const nsTArray<nsString>* aKeys, 
                                              const nsTArray<nsString>* aValues,
                                              const PRUint32 aFlags)
 {
   Notify();
   return NS_OK;
--- a/editor/composer/src/nsEditorParserObserver.h
+++ b/editor/composer/src/nsEditorParserObserver.h
@@ -54,17 +54,17 @@ public:
 
   NS_DECL_ISUPPORTS
 
   /* method for nsIElementObserver */
   NS_IMETHOD                Notify(PRUint32 aDocumentID, eHTMLTags aTag, PRUint32 numOfAttributes, 
                                     const PRUnichar* nameArray[], const PRUnichar* valueArray[]);
   NS_IMETHOD                Notify(PRUint32 aDocumentID, const PRUnichar* aTag, PRUint32 numOfAttributes, 
                                     const PRUnichar* nameArray[], const PRUnichar* valueArray[]);
-  NS_IMETHOD                Notify(nsISupports* aWebShell, 
+  NS_IMETHOD                Notify(nsISupports* aDocShell, 
                                    nsISupports* aChannel,
                                    const PRUnichar* aTag, 
                                    const nsTArray<nsString>* aKeys, 
                                    const nsTArray<nsString>* aValues,
                                    const PRUint32 aFlags);
 
   /* methods for nsIObserver */
   NS_DECL_NSIOBSERVER
--- a/embedding/browser/webBrowser/nsWebBrowser.cpp
+++ b/embedding/browser/webBrowser/nsWebBrowser.cpp
@@ -1131,17 +1131,17 @@ NS_IMETHODIMP nsWebBrowser::Create()
       widgetInit.mWindowType = eWindowType_child;
       nsIntRect bounds(mInitInfo->x, mInitInfo->y, mInitInfo->cx, mInitInfo->cy);
       
       mInternalWidget->SetClientData(static_cast<nsWebBrowser *>(this));
       mInternalWidget->Create(mParentNativeWindow, bounds, nsWebBrowser::HandleEvent,
                               nsnull, nsnull, nsnull, &widgetInit);  
       }
 
-   nsCOMPtr<nsIDocShell> docShell(do_CreateInstance("@mozilla.org/webshell;1"));
+   nsCOMPtr<nsIDocShell> docShell(do_CreateInstance("@mozilla.org/docshell;1"));
    NS_ENSURE_SUCCESS(SetDocShell(docShell), NS_ERROR_FAILURE);
 
    // get the system default window background colour
    {
       nsCOMPtr<nsILookAndFeel> laf = do_GetService(kLookAndFeelCID);
       laf->GetColor(nsILookAndFeel::eColor_WindowBackground, mBackgroundColor);
    }
 
--- a/intl/chardet/public/nsICharsetDetectionAdaptor.h
+++ b/intl/chardet/public/nsICharsetDetectionAdaptor.h
@@ -57,17 +57,17 @@ class nsIParser;
 
 class nsICharsetDetectionAdaptor : public nsISupports {
 public:  
   NS_DECLARE_STATIC_IID_ACCESSOR(NS_ICHARSETDETECTIONADAPTOR_IID)
   /*   
      Initialize it by setup the nsICharsetDetector and the 
      nsIWebShellServices
    */
-  NS_IMETHOD Init(nsIWebShellServices* aWebShell, nsICharsetDetector *aDetector, 
+  NS_IMETHOD Init(nsIWebShellServices* aDocShell, nsICharsetDetector *aDetector, 
                   nsIDocument* aDocument, nsIParser* aParser, 
                   const char* aCharset, const char* aCommand=nsnull) = 0;
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(nsICharsetDetectionAdaptor,
                               NS_ICHARSETDETECTIONADAPTOR_IID)
 
 #endif /* nsICDETAdaptor_h__ */
--- a/intl/chardet/src/nsMetaCharsetObserver.cpp
+++ b/intl/chardet/src/nsMetaCharsetObserver.cpp
@@ -129,40 +129,40 @@ NS_IMETHODIMP nsMetaCharsetObserver::Not
    for(i=0;i<numOfAttributes;i++)
    {
        keys.Push((void*)nameArray[i]);
        values.Push((void*)valueArray[i]);
    }
    return NS_OK;//Notify((nsISupports*)aDocumentID, &keys, &values);
 }
 NS_IMETHODIMP nsMetaCharsetObserver::Notify(
-                     nsISupports* aWebShell,
+                     nsISupports* aDocShell,
                      nsISupports* aChannel,
                      const PRUnichar* aTag, 
                      const nsTArray<nsString>* keys, 
                      const nsTArray<nsString>* values,
                      const PRUint32 aFlags)
 {
   nsresult result = NS_OK;
   // bug 125317 - document.write content is already an unicode content.
   if (!(aFlags & nsIElementObserver::IS_DOCUMENT_WRITE)) {
     if(!nsDependentString(aTag).LowerCaseEqualsLiteral("meta")) {
         result = NS_ERROR_ILLEGAL_VALUE;
     }
     else {
-        result = Notify(aWebShell, aChannel, keys, values);
+        result = Notify(aDocShell, aChannel, keys, values);
     }
   }
   return result;
 }
 
 #define IS_SPACE_CHARS(ch)  (ch == ' ' || ch == '\b' || ch == '\r' || ch == '\n')
 
 NS_IMETHODIMP nsMetaCharsetObserver::Notify(
-                    nsISupports* aWebShell,
+                    nsISupports* aDocShell,
                     nsISupports* aChannel,
                     const nsTArray<nsString>* keys, 
                     const nsTArray<nsString>* values)
 {
     NS_PRECONDITION(keys!=nsnull && values!=nsnull,"Need key-value pair");
 
     PRUint32 numOfAttributes = keys->Length();
     NS_ASSERTION( numOfAttributes == values->Length(), "size mismatch");
@@ -294,17 +294,17 @@ NS_IMETHODIMP nsMetaCharsetObserver::Not
                         if (!preferred.EqualsLiteral("UTF-16") &&
                             !preferred.EqualsLiteral("UTF-16BE") &&
                             !preferred.EqualsLiteral("UTF-16LE") &&
                             !preferred.EqualsLiteral("UTF-32") &&
                             !preferred.EqualsLiteral("UTF-32BE") &&
                             !preferred.EqualsLiteral("UTF-32LE")) {
                           // Propagate the error message so that the parser can
                           // shutdown correctly. - Ref. Bug 96440
-                          res = NotifyWebShell(aWebShell,
+                          res = NotifyDocShell(aDocShell,
                                                aChannel,
                                                preferred.get(),
                                                kCharsetFromMetaTag);
                         }
                      } // if(NS_SUCCEEDED(res)
                  }
              }
              else {
@@ -314,17 +314,17 @@ NS_IMETHODIMP nsMetaCharsetObserver::Not
       } // if
     }
     else
     {
       nsAutoString compatCharset;
       if (NS_SUCCEEDED(GetCharsetFromCompatibilityTag(keys, values, compatCharset)))
       {
         if (!compatCharset.IsEmpty()) {
-          res = NotifyWebShell(aWebShell,
+          res = NotifyDocShell(aDocShell,
                                aChannel,
                                NS_ConvertUTF16toUTF8(compatCharset).get(), 
                                kCharsetFromMetaTag);
         }
       }
     }
     return res;
 }
--- a/intl/chardet/src/nsObserverBase.cpp
+++ b/intl/chardet/src/nsObserverBase.cpp
@@ -30,28 +30,28 @@
  * use your version of this file under the terms of the MPL, indicate your
  * decision by deleting the provisions above and replace them with the notice
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
-//#define DONT_INFORM_WEBSHELL
+//#define DONT_INFORM_DOCSHELL
 
 #include "nsIServiceManager.h"
 #include "nsIWebShellServices.h"
 #include "nsObserverBase.h"
 #include "nsString.h"
 #include "nsIHttpChannel.h"
 
 
 
 //-------------------------------------------------------------------------
-NS_IMETHODIMP nsObserverBase::NotifyWebShell(nsISupports* aWebShell,
+NS_IMETHODIMP nsObserverBase::NotifyDocShell(nsISupports* aDocShell,
                                              nsISupports* aChannel,
                                              const char* charset, 
                                              PRInt32 source)
 {
 
    nsresult rv  = NS_OK;
    nsresult res = NS_OK;
 
@@ -60,20 +60,20 @@ NS_IMETHODIMP nsObserverBase::NotifyWebS
      nsCAutoString method;
      httpChannel->GetRequestMethod(method);
      if (method.EqualsLiteral("POST")) { // XXX What about PUT, etc?
        return NS_OK;
      }
    }
 
    nsCOMPtr<nsIWebShellServices> wss;
-   wss = do_QueryInterface(aWebShell,&res);
+   wss = do_QueryInterface(aDocShell,&res);
    if (NS_SUCCEEDED(res)) {
 
-#ifndef DONT_INFORM_WEBSHELL
+#ifndef DONT_INFORM_DOCSHELL
      // ask the webshellservice to load the URL
      if (NS_FAILED( res = wss->SetRendering(PR_FALSE) ))
        rv = res;
 
      // XXX nisheeth, uncomment the following two line to see the reent problem
 
      else if (NS_FAILED(res = wss->StopDocumentLoad())){
              rv = wss->SetRendering(PR_TRUE); // turn on the rendering so at least we will see something.
--- a/intl/chardet/src/nsObserverBase.h
+++ b/intl/chardet/src/nsObserverBase.h
@@ -54,16 +54,16 @@ public:
   /*
    *   Subject call observer when the parser hit the tag
    *   @param aDocumentID- ID of the document
    *   @param aTag- the tag
    *   @param valueArray - array of value
    */
 protected:
 
-  NS_IMETHOD NotifyWebShell(nsISupports* aWebShell,
+  NS_IMETHOD NotifyDocShell(nsISupports* aDocShell,
                             nsISupports* aChannel,
                             const char* charset, 
                             PRInt32 source);
 
 };
 
 #endif /* nsObserverBase_h__ */
--- a/intl/chardet/src/nsXMLEncodingObserver.cpp
+++ b/intl/chardet/src/nsXMLEncodingObserver.cpp
@@ -173,17 +173,17 @@ NS_IMETHODIMP nsXMLEncodingObserver::Not
                     res = calias->Equals( encoding, currentCharset, &same);
                     if(NS_SUCCEEDED(res) && (! same))
                     {
                           nsCAutoString preferred;
                           res = calias->GetPreferred(encoding,
                                                      preferred);
                           if(NS_SUCCEEDED(res))
                           {
-                            res = NotifyWebShell(0,0, preferred.get(), kCharsetFromMetaTag );
+                            res = NotifyDocShell(0,0, preferred.get(), kCharsetFromMetaTag );
                             return res;
                           } // if check for GetPreferred
                     } // if check res for Equals
                 } // if check res for GetService
             } // if Equals
        } // if 
     } // if 
 
--- a/intl/chardet/src/nsXMLEncodingObserver.h
+++ b/intl/chardet/src/nsXMLEncodingObserver.h
@@ -64,17 +64,17 @@ public:
    *   @param numOfAttributes - number of attributes
    *   @param nameArray - array of name. 
    *   @param valueArray - array of value
    */
   NS_IMETHOD Notify(PRUint32 aDocumentID, eHTMLTags aTag, PRUint32 numOfAttributes, 
                     const PRUnichar* nameArray[], const PRUnichar* valueArray[]);
   NS_IMETHOD Notify(PRUint32 aDocumentID, const PRUnichar* aTag, PRUint32 numOfAttributes, 
                     const PRUnichar* nameArray[], const PRUnichar* valueArray[]);
-  NS_IMETHOD Notify(nsISupports* aWebShell,
+  NS_IMETHOD Notify(nsISupports* aDocShell,
                     nsISupports* aChannel,
                     const PRUnichar* aTag, 
                     const nsTArray<nsString>* keys, 
                     const nsTArray<nsString>* values,
                     const PRUint32 aFlags)
   { return NS_ERROR_NOT_IMPLEMENTED; }
 
   NS_DECL_ISUPPORTS
--- a/layout/base/nsCSSFrameConstructor.cpp
+++ b/layout/base/nsCSSFrameConstructor.cpp
@@ -2856,17 +2856,17 @@ nsCSSFrameConstructor::ConstructRootFram
 
   // --------- IF SCROLLABLE WRAP IN SCROLLFRAME --------
 
   // If the device supports scrolling (e.g., in galley mode on the screen and
   // for print-preview, but not when printing), then create a scroll frame that
   // will act as the scrolling mechanism for the viewport. 
   // XXX Do we even need a viewport when printing to a printer?
 
-  // As long as the webshell doesn't prohibit it, and the device supports
+  // As long as the docshell doesn't prohibit it, and the device supports
   // it, create a scroll frame that will act as the scolling mechanism for
   // the viewport.
   //
   // Threre are three possible values stored in the docshell:
   //  1) nsIScrollable::Scrollbar_Never = no scrollbars
   //  2) nsIScrollable::Scrollbar_Auto = scrollbars appear if needed
   //  3) nsIScrollable::Scrollbar_Always = scrollbars always
   // Only need to create a scroll frame/view for cases 2 and 3.
--- a/layout/base/nsDocumentViewer.cpp
+++ b/layout/base/nsDocumentViewer.cpp
@@ -1325,17 +1325,17 @@ DocumentViewerImpl::Close(nsISHEntry *aS
   // A Close was called while we were printing
   // so don't clear the ScriptGlobalObject
   // or clear the mDocument below
   if (mPrintEngine && !mClosingWhilePrinting) {
     mClosingWhilePrinting = PR_TRUE;
   } else
 #endif
     {
-      // out of band cleanup of webshell
+      // out of band cleanup of docshell
       mDocument->SetScriptGlobalObject(nsnull);
 
       if (!mSHEntry && mDocument)
         mDocument->RemovedFromDocShell();
     }
 
   if (mFocusListener && mDocument) {
     mDocument->RemoveEventListenerByIID(mFocusListener,
--- a/modules/plugin/base/src/nsPluginHostImpl.cpp
+++ b/modules/plugin/base/src/nsPluginHostImpl.cpp
@@ -5590,17 +5590,17 @@ NS_IMETHODIMP nsPluginHostImpl::NewPlugi
         }
       }
 
       nsCOMPtr<nsIChannel> channel;
 
       rv = NS_NewChannel(getter_AddRefs(channel), url, nsnull,
         nsnull, /* do not add this internal plugin's channel
                 on the load group otherwise this channel could be canceled
-                form |nsWebShell::OnLinkClickSync| bug 166613 */
+                form |nsDocShell::OnLinkClickSync| bug 166613 */
         callbacks);
       if (NS_FAILED(rv))
         return rv;
 
       if (doc) {
         // Set the owner of channel to the document principal...
         channel->SetOwner(doc->NodePrincipal());
 
--- a/parser/htmlparser/public/nsIElementObserver.h
+++ b/parser/htmlparser/public/nsIElementObserver.h
@@ -72,17 +72,17 @@ public:
   NS_IMETHOD Notify(PRUint32 aDocumentID, eHTMLTags aTag, 
                     PRUint32 numOfAttributes, const PRUnichar* nameArray[], 
                     const PRUnichar* valueArray[]) = 0;
 
   NS_IMETHOD Notify(PRUint32 aDocumentID, const PRUnichar* aTag, 
                     PRUint32 numOfAttributes, const PRUnichar* nameArray[], 
                     const PRUnichar* valueArray[]) = 0;
   
-  NS_IMETHOD Notify(nsISupports* aWebShell, 
+  NS_IMETHOD Notify(nsISupports* aDocShell, 
                     nsISupports* aChannel,
                     const PRUnichar* aTag, 
                     const nsTArray<nsString>* aKeys, 
                     const nsTArray<nsString>* aValues,
                     const PRUint32 aFlags) = 0;
 
 };
 
--- a/parser/htmlparser/public/nsIParserService.h
+++ b/parser/htmlparser/public/nsIParserService.h
@@ -58,17 +58,17 @@ class nsIParserNode;
 
 
 class nsIObserverEntry : public nsISupports {
  public:
   NS_DECLARE_STATIC_IID_ACCESSOR(NS_IOBSERVERENTRY_IID)
 
   NS_IMETHOD Notify(nsIParserNode* aNode,
                     nsIParser* aParser,
-                    nsISupports* aWebShell,
+                    nsISupports* aDocShell,
                     const PRUint32 aFlags) = 0;
 
 };
 
 
 NS_DEFINE_STATIC_IID_ACCESSOR(nsIObserverEntry, NS_IOBSERVERENTRY_IID)
 
 class nsIParserService : public nsISupports {
--- a/parser/htmlparser/src/nsDTDUtils.cpp
+++ b/parser/htmlparser/src/nsDTDUtils.cpp
@@ -1045,17 +1045,17 @@ nsObserverEntry::~nsObserverEntry() {
       delete mObservers[i];
     }
   }
 }
 
 NS_IMETHODIMP
 nsObserverEntry::Notify(nsIParserNode* aNode,
                         nsIParser* aParser,
-                        nsISupports* aWebShell,
+                        nsISupports* aDocShell,
                         const PRUint32 aFlags) 
 {
   NS_ENSURE_ARG_POINTER(aNode);
   NS_ENSURE_ARG_POINTER(aParser);
 
   nsresult result = NS_OK;
   eHTMLTags theTag = (eHTMLTags)aNode->GetNodeType();
  
@@ -1095,17 +1095,17 @@ nsObserverEntry::Notify(nsIParserNode* a
         values.AppendElement(NS_LITERAL_STRING("text/html")); 
 
         nsCOMPtr<nsIChannel> channel;
         aParser->GetChannel(getter_AddRefs(channel));
 
         for (index=0;index<theObserversCount;++index) {
           nsIElementObserver* observer = theObservers->ObjectAt(index);
           if (observer) {
-            result = observer->Notify(aWebShell, channel,
+            result = observer->Notify(aDocShell, channel,
                                       nsHTMLTags::GetStringValue(theTag),
                                       &keys, &values, aFlags);
             if (NS_FAILED(result)) {
               break;
             }
 
             if (result == NS_HTMLPARSER_VALID_META_CHARSET) {
               // Inform the parser that this meta tag contained a valid
--- a/parser/htmlparser/src/nsDTDUtils.h
+++ b/parser/htmlparser/src/nsDTDUtils.h
@@ -430,17 +430,17 @@ inline PRBool FindTagInSet(PRInt32 aTag,
 class nsObserverEntry : public nsIObserverEntry {
 public:
   NS_DECL_ISUPPORTS
             nsObserverEntry(const nsAString& aString);
   virtual   ~nsObserverEntry();
 
   NS_IMETHOD Notify(nsIParserNode* aNode,
                     nsIParser* aParser,
-                    nsISupports* aWebShell,
+                    nsISupports* aDocShell,
                     const PRUint32 aFlags);
 
   nsresult   AddObserver(nsIElementObserver* aObserver,eHTMLTags aTag);
   void       RemoveObserver(nsIElementObserver* aObserver);
   PRBool     Matches(const nsAString& aTopic);
 
 protected:
   nsString mTopic;
--- a/toolkit/components/viewsource/content/viewSourceUtils.js
+++ b/toolkit/components/viewsource/content/viewSourceUtils.js
@@ -130,19 +130,22 @@ var gViewSourceUtils = {
           webBrowserPersist.progressListener = this.viewSourceProgressListener;
           webBrowserPersist.saveURI(uri, null, null, null, null, file);
 
           // register the file to be deleted on app exit
           Components.classes["@mozilla.org/uriloader/external-helper-app-service;1"]
                     .getService(Components.interfaces.nsPIExternalAppLauncher)
                     .deleteTemporaryFileOnExit(file);
         } else {
-          // we'll use nsIWebPageDescriptor to get the source because it may not have to refetch
-          // the file from the server
-          var webShell = Components.classes["@mozilla.org/webshell;1"].createInstance();
+          // we'll use nsIWebPageDescriptor to get the source because it may
+          // not have to refetch the file from the server
+          // XXXbz this is so broken...  This code doesn't set up this docshell
+          // at all correctly; if somehow the view-source stuff managed to
+          // execute script we'd be in big trouble here, I suspect.
+          var webShell = Components.classes["@mozilla.org/docshell;1"].createInstance();
           this.viewSourceProgressListener.webShell = webShell;
           var progress = webShell.QueryInterface(this.mnsIWebProgress);
           progress.addProgressListener(this.viewSourceProgressListener,
                                        this.mnsIWebProgress.NOTIFY_STATE_DOCUMENT);
           var pageLoader = webShell.QueryInterface(this.mnsIWebPageDescriptor);    
           pageLoader.loadPage(aPageDescriptor, this.mnsIWebPageDescriptor.DISPLAY_AS_SOURCE);
         }
       }
--- a/xpfe/appshell/src/nsWebShellWindow.cpp
+++ b/xpfe/appshell/src/nsWebShellWindow.cpp
@@ -214,17 +214,17 @@ nsresult nsWebShellWindow::Initialize(ns
                   nsnull,                             // Device context
                   aShell,                             // Application shell
                   nsnull,                             // nsIToolkit
                   &widgetInitData);                   // Widget initialization data
   mWindow->GetClientBounds(r);
   mWindow->SetBackgroundColor(NS_RGB(192,192,192));
 
   // Create web shell
-  mDocShell = do_CreateInstance("@mozilla.org/webshell;1");
+  mDocShell = do_CreateInstance("@mozilla.org/docshell;1");
   NS_ENSURE_TRUE(mDocShell, NS_ERROR_FAILURE);
 
   // Make sure to set the item type on the docshell _before_ calling
   // Create() so it knows what type it is.
   nsCOMPtr<nsIDocShellTreeItem> docShellAsItem(do_QueryInterface(mDocShell));
   NS_ENSURE_TRUE(docShellAsItem, NS_ERROR_FAILURE);
   NS_ENSURE_SUCCESS(EnsureChromeTreeOwner(), NS_ERROR_FAILURE);
 
--- a/xpfe/browser/src/nsBrowserInstance.cpp
+++ b/xpfe/browser/src/nsBrowserInstance.cpp
@@ -80,18 +80,16 @@
 #include "nsIServiceManager.h"
 #include "nsIURL.h"
 #include "nsIIOService.h"
 #include "nsIWidget.h"
 #include "plstr.h"
 
 #include "nsIAppStartup.h"
 
-#include "nsDocShellCID.h"
-
 #include "nsIObserverService.h"
 
 #include "nsILocalFile.h"
 #include "nsDirectoryServiceDefs.h"
 
 #include "nsNetUtil.h"
 
 // Stuff to implement file download dialog.
@@ -400,17 +398,17 @@ nsBrowserInstance::ReinitializeContentVa
 
     mContentAreaDocShellWeak = do_GetWeakReference(docShell); // Weak reference
 
     if (APP_DEBUG) {
       nsCOMPtr<nsIDocShellTreeItem> docShellAsItem(do_QueryInterface(docShell));
       if (docShellAsItem) {
         nsXPIDLString name;
         docShellAsItem->GetName(getter_Copies(name));
-        printf("Attaching to Content WebShell [%s]\n", NS_LossyConvertUTF16toASCII(name).get());
+        printf("Attaching to Content DocShell [%s]\n", NS_LossyConvertUTF16toASCII(name).get());
       }
     }
   }
 }
 
 nsresult nsBrowserInstance::GetContentAreaDocShell(nsIDocShell** outDocShell)
 {
   nsCOMPtr<nsIDocShell> docShell(do_QueryReferent(mContentAreaDocShellWeak));
@@ -454,17 +452,17 @@ NS_INTERFACE_MAP_END
 nsresult
 nsBrowserInstance::LoadUrl(const PRUnichar * urlToLoad)
 {
   nsresult rv = NS_OK;
 
   nsCOMPtr<nsIDocShell> docShell;
   GetContentAreaDocShell(getter_AddRefs(docShell));
 
-  /* Ask nsWebShell to load the URl */
+  /* Ask nsDocShell to load the URl */
   nsCOMPtr<nsIWebNavigation> webNav(do_QueryInterface(docShell));
     
   // Normal browser.
   rv = webNav->LoadURI( urlToLoad,                          // URI string
                         nsIWebNavigation::LOAD_FLAGS_NONE,  // Load flags
                         nsnull,                             // Referring URI
                         nsnull,                             // Post data
                         nsnull );                           // Extra headers
@@ -509,17 +507,18 @@ nsBrowserInstance::SetWebShellWindow(nsI
     return NS_ERROR_FAILURE;
   }
 
   if (APP_DEBUG) {
     nsCOMPtr<nsIDocShellTreeItem> docShellAsItem =
       do_QueryInterface(win->GetDocShell());
 
     if (docShellAsItem) {
-      // inform our top level webshell that we are its parent URI content listener...
+      // inform our top level docshell that we are its parent URI
+      // content listener...
       nsXPIDLString name;
       docShellAsItem->GetName(getter_Copies(name));
       printf("Attaching to WebShellWindow[%s]\n", NS_LossyConvertUTF16toASCII(name).get());
     }
   }
 
   ReinitializeContentVariables();