LCOV - code coverage report
Current view: directory - content/base/src - nsFrameLoader.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 1030 2 0.2 %
Date: 2012-06-02 Functions: 91 2 2.2 %

       1                 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2                 : /* vim: set ts=2 sw=2 et tw=78: */
       3                 : /* ***** BEGIN LICENSE BLOCK *****
       4                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
       5                 :  *
       6                 :  * The contents of this file are subject to the Mozilla Public License Version
       7                 :  * 1.1 (the "License"); you may not use this file except in compliance with
       8                 :  * the License. You may obtain a copy of the License at
       9                 :  * http://www.mozilla.org/MPL/
      10                 :  *
      11                 :  * Software distributed under the License is distributed on an "AS IS" basis,
      12                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
      13                 :  * for the specific language governing rights and limitations under the
      14                 :  * License.
      15                 :  *
      16                 :  * The Original Code is Mozilla Communicator client code.
      17                 :  *
      18                 :  * The Initial Developer of the Original Code is
      19                 :  * Netscape Communications Corporation.
      20                 :  * Portions created by the Initial Developer are Copyright (C) 1998
      21                 :  * the Initial Developer. All Rights Reserved.
      22                 :  *
      23                 :  * Contributor(s):
      24                 :  *   Johnny Stenback <jst@netscape.com> (original author)
      25                 :  *   Boris Zbarsky <bzbarsky@mit.edu>
      26                 :  *   Frederic Plourde <frederic.plourde@polymtl.ca>
      27                 :  *
      28                 :  * Alternatively, the contents of this file may be used under the terms of
      29                 :  * either of the GNU General Public License Version 2 or later (the "GPL"),
      30                 :  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      31                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      32                 :  * of those above. If you wish to allow use of your version of this file only
      33                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      34                 :  * use your version of this file under the terms of the MPL, indicate your
      35                 :  * decision by deleting the provisions above and replace them with the notice
      36                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      37                 :  * the provisions above, a recipient may use your version of this file under
      38                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      39                 :  *
      40                 :  * ***** END LICENSE BLOCK ***** */
      41                 : 
      42                 : /*
      43                 :  * Class for managing loading of a subframe (creation of the docshell,
      44                 :  * handling of loads in it, recursion-checking).
      45                 :  */
      46                 : 
      47                 : #include "base/basictypes.h"
      48                 : 
      49                 : #include "prenv.h"
      50                 : 
      51                 : #include "nsIDOMHTMLIFrameElement.h"
      52                 : #include "nsIDOMHTMLFrameElement.h"
      53                 : #include "nsIDOMWindow.h"
      54                 : #include "nsIPresShell.h"
      55                 : #include "nsIContent.h"
      56                 : #include "nsIContentViewer.h"
      57                 : #include "nsIDocument.h"
      58                 : #include "nsIDOMDocument.h"
      59                 : #include "nsIDOMWindow.h"
      60                 : #include "nsPIDOMWindow.h"
      61                 : #include "nsIWebNavigation.h"
      62                 : #include "nsIWebProgress.h"
      63                 : #include "nsIDocShell.h"
      64                 : #include "nsIDocShellTreeItem.h"
      65                 : #include "nsIDocShellTreeNode.h"
      66                 : #include "nsIDocShellTreeOwner.h"
      67                 : #include "nsIDocShellLoadInfo.h"
      68                 : #include "nsIBaseWindow.h"
      69                 : #include "nsContentUtils.h"
      70                 : #include "nsIXPConnect.h"
      71                 : #include "nsIJSContextStack.h"
      72                 : #include "nsUnicharUtils.h"
      73                 : #include "nsIScriptGlobalObject.h"
      74                 : #include "nsIScriptSecurityManager.h"
      75                 : #include "nsIScrollable.h"
      76                 : #include "nsFrameLoader.h"
      77                 : #include "nsIDOMEventTarget.h"
      78                 : #include "nsIFrame.h"
      79                 : #include "nsIScrollableFrame.h"
      80                 : #include "nsSubDocumentFrame.h"
      81                 : #include "nsDOMError.h"
      82                 : #include "nsGUIEvent.h"
      83                 : #include "nsEventDispatcher.h"
      84                 : #include "nsISHistory.h"
      85                 : #include "nsISHistoryInternal.h"
      86                 : #include "nsIDocShellHistory.h"
      87                 : #include "nsIDOMHTMLDocument.h"
      88                 : #include "nsIXULWindow.h"
      89                 : #include "nsIEditor.h"
      90                 : #include "nsIEditorDocShell.h"
      91                 : #include "nsIMozBrowserFrame.h"
      92                 : 
      93                 : #include "nsLayoutUtils.h"
      94                 : #include "nsIView.h"
      95                 : #include "nsAsyncDOMEvent.h"
      96                 : 
      97                 : #include "nsIURI.h"
      98                 : #include "nsIURL.h"
      99                 : #include "nsNetUtil.h"
     100                 : 
     101                 : #include "nsGkAtoms.h"
     102                 : #include "nsINameSpaceManager.h"
     103                 : 
     104                 : #include "nsThreadUtils.h"
     105                 : #include "nsIContentViewer.h"
     106                 : #include "nsIView.h"
     107                 : 
     108                 : #include "nsIDOMChromeWindow.h"
     109                 : #include "nsInProcessTabChildGlobal.h"
     110                 : 
     111                 : #include "Layers.h"
     112                 : 
     113                 : #include "ContentParent.h"
     114                 : #include "TabParent.h"
     115                 : #include "mozilla/GuardObjects.h"
     116                 : #include "mozilla/Preferences.h"
     117                 : #include "mozilla/unused.h"
     118                 : #include "mozilla/dom/Element.h"
     119                 : #include "mozilla/layout/RenderFrameParent.h"
     120                 : 
     121                 : #include "jsapi.h"
     122                 : 
     123                 : using namespace mozilla;
     124                 : using namespace mozilla::dom;
     125                 : using namespace mozilla::layers;
     126                 : using namespace mozilla::layout;
     127                 : typedef FrameMetrics::ViewID ViewID;
     128                 : 
     129                 : class nsAsyncDocShellDestroyer : public nsRunnable
     130               0 : {
     131                 : public:
     132               0 :   nsAsyncDocShellDestroyer(nsIDocShell* aDocShell)
     133               0 :     : mDocShell(aDocShell)
     134                 :   {
     135               0 :   }
     136                 : 
     137               0 :   NS_IMETHOD Run()
     138                 :   {
     139               0 :     nsCOMPtr<nsIBaseWindow> base_win(do_QueryInterface(mDocShell));
     140               0 :     if (base_win) {
     141               0 :       base_win->Destroy();
     142                 :     }
     143               0 :     return NS_OK;
     144                 :   }
     145                 :   nsRefPtr<nsIDocShell> mDocShell;
     146                 : };
     147                 : 
     148               0 : static void InvalidateFrame(nsIFrame* aFrame, PRUint32 aFlags)
     149                 : {
     150               0 :   if (!aFrame)
     151               0 :     return;
     152               0 :   nsRect rect = nsRect(nsPoint(0, 0), aFrame->GetRect().Size());
     153               0 :   aFrame->InvalidateWithFlags(rect, aFlags);
     154                 : }
     155                 : 
     156               0 : NS_IMPL_ISUPPORTS1(nsContentView, nsIContentView)
     157                 : 
     158                 : bool
     159               0 : nsContentView::IsRoot() const
     160                 : {
     161               0 :   return mScrollId == FrameMetrics::ROOT_SCROLL_ID;
     162                 : }
     163                 : 
     164                 : nsresult
     165               0 : nsContentView::Update(const ViewConfig& aConfig)
     166                 : {
     167               0 :   if (aConfig == mConfig) {
     168               0 :     return NS_OK;
     169                 :   }
     170               0 :   mConfig = aConfig;
     171                 : 
     172                 :   // View changed.  Try to locate our subdoc frame and invalidate
     173                 :   // it if found.
     174               0 :   if (!mFrameLoader) {
     175               0 :     if (IsRoot()) {
     176                 :       // Oops, don't have a frame right now.  That's OK; the view
     177                 :       // config persists and will apply to the next frame we get, if we
     178                 :       // ever get one.
     179               0 :       return NS_OK;
     180                 :     } else {
     181                 :       // This view is no longer valid.
     182               0 :       return NS_ERROR_NOT_AVAILABLE;
     183                 :     }
     184                 :   }
     185                 : 
     186               0 :   if (RenderFrameParent* rfp = mFrameLoader->GetCurrentRemoteFrame()) {
     187               0 :     rfp->ContentViewScaleChanged(this);
     188                 :   }
     189                 : 
     190                 :   // XXX could be clever here and compute a smaller invalidation
     191                 :   // rect
     192                 :   // NB: we pass INVALIDATE_NO_THEBES_LAYERS here to keep view
     193                 :   // semantics the same for both in-process and out-of-process
     194                 :   // <browser>.  This is just a transform of the layer subtree in
     195                 :   // both.
     196               0 :   InvalidateFrame(mFrameLoader->GetPrimaryFrameOfOwningContent(), nsIFrame::INVALIDATE_NO_THEBES_LAYERS);
     197               0 :   return NS_OK;
     198                 : }
     199                 : 
     200                 : NS_IMETHODIMP
     201               0 : nsContentView::ScrollTo(float aXpx, float aYpx)
     202                 : {
     203               0 :   ViewConfig config(mConfig);
     204                 :   config.mScrollOffset = nsPoint(nsPresContext::CSSPixelsToAppUnits(aXpx),
     205               0 :                                  nsPresContext::CSSPixelsToAppUnits(aYpx));
     206               0 :   return Update(config);
     207                 : }
     208                 : 
     209                 : NS_IMETHODIMP
     210               0 : nsContentView::ScrollBy(float aDXpx, float aDYpx)
     211                 : {
     212               0 :   ViewConfig config(mConfig);
     213                 :   config.mScrollOffset.MoveBy(nsPresContext::CSSPixelsToAppUnits(aDXpx),
     214               0 :                               nsPresContext::CSSPixelsToAppUnits(aDYpx));
     215               0 :   return Update(config);
     216                 : }
     217                 : 
     218                 : NS_IMETHODIMP
     219               0 : nsContentView::SetScale(float aXScale, float aYScale)
     220                 : {
     221               0 :   ViewConfig config(mConfig);
     222               0 :   config.mXScale = aXScale;
     223               0 :   config.mYScale = aYScale;
     224               0 :   return Update(config);
     225                 : }
     226                 : 
     227                 : NS_IMETHODIMP
     228               0 : nsContentView::GetScrollX(float* aViewScrollX)
     229                 : {
     230                 :   *aViewScrollX = nsPresContext::AppUnitsToFloatCSSPixels(
     231               0 :     mConfig.mScrollOffset.x);
     232               0 :   return NS_OK;
     233                 : }
     234                 : 
     235                 : NS_IMETHODIMP
     236               0 : nsContentView::GetScrollY(float* aViewScrollY)
     237                 : {
     238                 :   *aViewScrollY = nsPresContext::AppUnitsToFloatCSSPixels(
     239               0 :     mConfig.mScrollOffset.y);
     240               0 :   return NS_OK;
     241                 : }
     242                 : 
     243                 : NS_IMETHODIMP
     244               0 : nsContentView::GetViewportWidth(float* aWidth)
     245                 : {
     246               0 :   *aWidth = nsPresContext::AppUnitsToFloatCSSPixels(mViewportSize.width);
     247               0 :   return NS_OK;
     248                 : }
     249                 : 
     250                 : NS_IMETHODIMP
     251               0 : nsContentView::GetViewportHeight(float* aHeight)
     252                 : {
     253               0 :   *aHeight = nsPresContext::AppUnitsToFloatCSSPixels(mViewportSize.height);
     254               0 :   return NS_OK;
     255                 : }
     256                 : 
     257                 : NS_IMETHODIMP
     258               0 : nsContentView::GetContentWidth(float* aWidth)
     259                 : {
     260               0 :   *aWidth = nsPresContext::AppUnitsToFloatCSSPixels(mContentSize.width);
     261               0 :   return NS_OK;
     262                 : }
     263                 : 
     264                 : NS_IMETHODIMP
     265               0 : nsContentView::GetContentHeight(float* aHeight)
     266                 : {
     267               0 :   *aHeight = nsPresContext::AppUnitsToFloatCSSPixels(mContentSize.height);
     268               0 :   return NS_OK;
     269                 : }
     270                 : 
     271                 : NS_IMETHODIMP
     272               0 : nsContentView::GetId(nsContentViewId* aId)
     273                 : {
     274                 :   NS_ASSERTION(sizeof(nsContentViewId) == sizeof(ViewID),
     275                 :                "ID size for XPCOM ID and internal ID type are not the same!");
     276               0 :   *aId = mScrollId;
     277               0 :   return NS_OK;
     278                 : }
     279                 : 
     280                 : // Bug 136580: Limit to the number of nested content frames that can have the
     281                 : //             same URL. This is to stop content that is recursively loading
     282                 : //             itself.  Note that "#foo" on the end of URL doesn't affect
     283                 : //             whether it's considered identical, but "?foo" or ";foo" are
     284                 : //             considered and compared.
     285                 : // Bug 228829: Limit this to 1, like IE does.
     286                 : #define MAX_SAME_URL_CONTENT_FRAMES 1
     287                 : 
     288                 : // Bug 8065: Limit content frame depth to some reasonable level. This
     289                 : // does not count chrome frames when determining depth, nor does it
     290                 : // prevent chrome recursion.  Number is fairly arbitrary, but meant to
     291                 : // keep number of shells to a reasonable number on accidental recursion with a
     292                 : // small (but not 1) branching factor.  With large branching factors the number
     293                 : // of shells can rapidly become huge and run us out of memory.  To solve that,
     294                 : // we'd need to re-institute a fixed version of bug 98158.
     295                 : #define MAX_DEPTH_CONTENT_FRAMES 10
     296                 : 
     297            1464 : NS_IMPL_CYCLE_COLLECTION_CLASS(nsFrameLoader)
     298                 : 
     299               0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsFrameLoader)
     300               0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mDocShell)
     301               0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mMessageManager)
     302               0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mChildMessageManager)
     303               0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_END
     304                 : 
     305               0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsFrameLoader)
     306               0 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mDocShell)
     307               0 :   NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "nsFrameLoader::mMessageManager");
     308               0 :   cb.NoteXPCOMChild(static_cast<nsIContentFrameMessageManager*>(tmp->mMessageManager.get()));
     309               0 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mChildMessageManager)
     310               0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
     311                 : 
     312               0 : NS_IMPL_CYCLE_COLLECTING_ADDREF(nsFrameLoader)
     313               0 : NS_IMPL_CYCLE_COLLECTING_RELEASE(nsFrameLoader)
     314                 : 
     315               0 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsFrameLoader)
     316               0 :   NS_INTERFACE_MAP_ENTRY(nsIFrameLoader)
     317               0 :   NS_INTERFACE_MAP_ENTRY(nsIContentViewManager)
     318               0 :   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIFrameLoader)
     319               0 : NS_INTERFACE_MAP_END
     320                 : 
     321               0 : nsFrameLoader::nsFrameLoader(Element* aOwner, bool aNetworkCreated)
     322                 :   : mOwnerContent(aOwner)
     323                 :   , mDepthTooGreat(false)
     324                 :   , mIsTopLevelContent(false)
     325                 :   , mDestroyCalled(false)
     326                 :   , mNeedsAsyncDestroy(false)
     327                 :   , mInSwap(false)
     328                 :   , mInShow(false)
     329                 :   , mHideCalled(false)
     330                 :   , mNetworkCreated(aNetworkCreated)
     331                 :   , mDelayRemoteDialogs(false)
     332                 :   , mRemoteBrowserShown(false)
     333                 :   , mRemoteFrame(false)
     334                 :   , mClipSubdocument(true)
     335                 :   , mClampScrollPosition(true)
     336                 :   , mCurrentRemoteFrame(nsnull)
     337                 :   , mRemoteBrowser(nsnull)
     338                 :   , mRenderMode(RENDER_MODE_DEFAULT)
     339               0 :   , mEventMode(EVENT_MODE_NORMAL_DISPATCH)
     340                 : {
     341               0 : }
     342                 : 
     343                 : nsFrameLoader*
     344               0 : nsFrameLoader::Create(Element* aOwner, bool aNetworkCreated)
     345                 : {
     346               0 :   NS_ENSURE_TRUE(aOwner, nsnull);
     347               0 :   nsIDocument* doc = aOwner->OwnerDoc();
     348               0 :   NS_ENSURE_TRUE(!doc->GetDisplayDocument() &&
     349                 :                  ((!doc->IsLoadedAsData() && aOwner->GetCurrentDoc()) ||
     350                 :                    doc->IsStaticDocument()),
     351                 :                  nsnull);
     352                 : 
     353               0 :   return new nsFrameLoader(aOwner, aNetworkCreated);
     354                 : }
     355                 : 
     356                 : NS_IMETHODIMP
     357               0 : nsFrameLoader::LoadFrame()
     358                 : {
     359               0 :   NS_ENSURE_TRUE(mOwnerContent, NS_ERROR_NOT_INITIALIZED);
     360                 : 
     361               0 :   nsAutoString src;
     362               0 :   GetURL(src);
     363                 : 
     364               0 :   src.Trim(" \t\n\r");
     365                 : 
     366               0 :   if (src.IsEmpty()) {
     367               0 :     src.AssignLiteral("about:blank");
     368                 :   }
     369                 : 
     370               0 :   nsIDocument* doc = mOwnerContent->OwnerDoc();
     371               0 :   if (doc->IsStaticDocument()) {
     372               0 :     return NS_OK;
     373                 :   }
     374                 : 
     375               0 :   nsCOMPtr<nsIURI> base_uri = mOwnerContent->GetBaseURI();
     376               0 :   const nsAFlatCString &doc_charset = doc->GetDocumentCharacterSet();
     377               0 :   const char *charset = doc_charset.IsEmpty() ? nsnull : doc_charset.get();
     378                 : 
     379               0 :   nsCOMPtr<nsIURI> uri;
     380               0 :   nsresult rv = NS_NewURI(getter_AddRefs(uri), src, charset, base_uri);
     381                 : 
     382                 :   // If the URI was malformed, try to recover by loading about:blank.
     383               0 :   if (rv == NS_ERROR_MALFORMED_URI) {
     384               0 :     rv = NS_NewURI(getter_AddRefs(uri), NS_LITERAL_STRING("about:blank"),
     385               0 :                    charset, base_uri);
     386                 :   }
     387                 : 
     388               0 :   if (NS_SUCCEEDED(rv)) {
     389               0 :     rv = LoadURI(uri);
     390                 :   }
     391                 :   
     392               0 :   if (NS_FAILED(rv)) {
     393               0 :     FireErrorEvent();
     394                 : 
     395               0 :     return rv;
     396                 :   }
     397                 : 
     398               0 :   return NS_OK;
     399                 : }
     400                 : 
     401                 : void
     402               0 : nsFrameLoader::FireErrorEvent()
     403                 : {
     404               0 :   if (mOwnerContent) {
     405                 :     nsRefPtr<nsAsyncDOMEvent> event =
     406               0 :       new nsLoadBlockingAsyncDOMEvent(mOwnerContent, NS_LITERAL_STRING("error"),
     407               0 :                                       false, false);
     408               0 :     event->PostDOMEvent();
     409                 :   }
     410               0 : }
     411                 : 
     412                 : NS_IMETHODIMP
     413               0 : nsFrameLoader::LoadURI(nsIURI* aURI)
     414                 : {
     415               0 :   if (!aURI)
     416               0 :     return NS_ERROR_INVALID_POINTER;
     417               0 :   NS_ENSURE_STATE(!mDestroyCalled && mOwnerContent);
     418                 : 
     419               0 :   nsCOMPtr<nsIDocument> doc = mOwnerContent->OwnerDoc();
     420                 : 
     421               0 :   nsresult rv = CheckURILoad(aURI);
     422               0 :   NS_ENSURE_SUCCESS(rv, rv);
     423                 : 
     424               0 :   mURIToLoad = aURI;
     425               0 :   rv = doc->InitializeFrameLoader(this);
     426               0 :   if (NS_FAILED(rv)) {
     427               0 :     mURIToLoad = nsnull;
     428                 :   }
     429               0 :   return rv;
     430                 : }
     431                 : 
     432                 : nsresult
     433               0 : nsFrameLoader::ReallyStartLoading()
     434                 : {
     435               0 :   nsresult rv = ReallyStartLoadingInternal();
     436               0 :   if (NS_FAILED(rv)) {
     437               0 :     FireErrorEvent();
     438                 :   }
     439                 :   
     440               0 :   return rv;
     441                 : }
     442                 : 
     443                 : nsresult
     444               0 : nsFrameLoader::ReallyStartLoadingInternal()
     445                 : {
     446               0 :   NS_ENSURE_STATE(mURIToLoad && mOwnerContent && mOwnerContent->IsInDoc());
     447                 : 
     448               0 :   nsresult rv = MaybeCreateDocShell();
     449               0 :   if (NS_FAILED(rv)) {
     450               0 :     return rv;
     451                 :   }
     452                 : 
     453               0 :   if (mRemoteFrame) {
     454               0 :     if (!mRemoteBrowser) {
     455               0 :       TryRemoteBrowser();
     456                 : 
     457               0 :       if (!mRemoteBrowser) {
     458               0 :         NS_WARNING("Couldn't create child process for iframe.");
     459               0 :         return NS_ERROR_FAILURE;
     460                 :       }
     461                 :     }
     462                 : 
     463                 :     // FIXME get error codes from child
     464               0 :     mRemoteBrowser->LoadURL(mURIToLoad);
     465               0 :     return NS_OK;
     466                 :   }
     467                 : 
     468               0 :   NS_ASSERTION(mDocShell,
     469                 :                "MaybeCreateDocShell succeeded with a null mDocShell");
     470                 : 
     471                 :   // Just to be safe, recheck uri.
     472               0 :   rv = CheckURILoad(mURIToLoad);
     473               0 :   NS_ENSURE_SUCCESS(rv, rv);
     474                 : 
     475               0 :   nsCOMPtr<nsIDocShellLoadInfo> loadInfo;
     476               0 :   mDocShell->CreateLoadInfo(getter_AddRefs(loadInfo));
     477               0 :   NS_ENSURE_TRUE(loadInfo, NS_ERROR_FAILURE);
     478                 : 
     479                 :   // We'll use our principal, not that of the document loaded inside us.  This
     480                 :   // is very important; needed to prevent XSS attacks on documents loaded in
     481                 :   // subframes!
     482               0 :   loadInfo->SetOwner(mOwnerContent->NodePrincipal());
     483                 : 
     484               0 :   nsCOMPtr<nsIURI> referrer;
     485               0 :   rv = mOwnerContent->NodePrincipal()->GetURI(getter_AddRefs(referrer));
     486               0 :   NS_ENSURE_SUCCESS(rv, rv);
     487                 : 
     488               0 :   loadInfo->SetReferrer(referrer);
     489                 : 
     490                 :   // Kick off the load...
     491               0 :   bool tmpState = mNeedsAsyncDestroy;
     492               0 :   mNeedsAsyncDestroy = true;
     493               0 :   rv = mDocShell->LoadURI(mURIToLoad, loadInfo,
     494               0 :                           nsIWebNavigation::LOAD_FLAGS_NONE, false);
     495               0 :   mNeedsAsyncDestroy = tmpState;
     496               0 :   mURIToLoad = nsnull;
     497               0 :   NS_ENSURE_SUCCESS(rv, rv);
     498                 : 
     499               0 :   return NS_OK;
     500                 : }
     501                 : 
     502                 : nsresult
     503               0 : nsFrameLoader::CheckURILoad(nsIURI* aURI)
     504                 : {
     505                 :   // Check for security.  The fun part is trying to figure out what principals
     506                 :   // to use.  The way I figure it, if we're doing a LoadFrame() accidentally
     507                 :   // (eg someone created a frame/iframe node, we're being parsed, XUL iframes
     508                 :   // are being reframed, etc.) then we definitely want to use the node
     509                 :   // principal of mOwnerContent for security checks.  If, on the other hand,
     510                 :   // someone's setting the src on our owner content, or created it via script,
     511                 :   // or whatever, then they can clearly access it... and we should still use
     512                 :   // the principal of mOwnerContent.  I don't think that leads to privilege
     513                 :   // escalation, and it's reasonably guaranteed to not lead to XSS issues
     514                 :   // (since caller can already access mOwnerContent in this case).  So just use
     515                 :   // the principal of mOwnerContent no matter what.  If script wants to run
     516                 :   // things with its own permissions, which differ from those of mOwnerContent
     517                 :   // (which means the script is privileged in some way) it should set
     518                 :   // window.location instead.
     519               0 :   nsIScriptSecurityManager *secMan = nsContentUtils::GetSecurityManager();
     520                 : 
     521                 :   // Get our principal
     522               0 :   nsIPrincipal* principal = mOwnerContent->NodePrincipal();
     523                 : 
     524                 :   // Check if we are allowed to load absURL
     525                 :   nsresult rv =
     526                 :     secMan->CheckLoadURIWithPrincipal(principal, aURI,
     527               0 :                                       nsIScriptSecurityManager::STANDARD);
     528               0 :   if (NS_FAILED(rv)) {
     529               0 :     return rv; // We're not
     530                 :   }
     531                 : 
     532                 :   // Bail out if this is an infinite recursion scenario
     533               0 :   rv = MaybeCreateDocShell();
     534               0 :   if (NS_FAILED(rv)) {
     535               0 :     return rv;
     536                 :   }
     537               0 :   if (mRemoteFrame) {
     538               0 :     return NS_OK;
     539                 :   }
     540               0 :   return CheckForRecursiveLoad(aURI);
     541                 : }
     542                 : 
     543                 : NS_IMETHODIMP
     544               0 : nsFrameLoader::GetDocShell(nsIDocShell **aDocShell)
     545                 : {
     546               0 :   *aDocShell = nsnull;
     547               0 :   nsresult rv = NS_OK;
     548                 : 
     549                 :   // If we have an owner, make sure we have a docshell and return
     550                 :   // that. If not, we're most likely in the middle of being torn down,
     551                 :   // then we just return null.
     552               0 :   if (mOwnerContent) {
     553               0 :     nsresult rv = MaybeCreateDocShell();
     554               0 :     if (NS_FAILED(rv))
     555               0 :       return rv;
     556               0 :     if (mRemoteFrame) {
     557               0 :       NS_WARNING("No docshells for remote frames!");
     558               0 :       return rv;
     559                 :     }
     560               0 :     NS_ASSERTION(mDocShell,
     561                 :                  "MaybeCreateDocShell succeeded, but null mDocShell");
     562                 :   }
     563                 : 
     564               0 :   *aDocShell = mDocShell;
     565               0 :   NS_IF_ADDREF(*aDocShell);
     566                 : 
     567               0 :   return rv;
     568                 : }
     569                 : 
     570                 : void
     571               0 : nsFrameLoader::Finalize()
     572                 : {
     573               0 :   nsCOMPtr<nsIBaseWindow> base_win(do_QueryInterface(mDocShell));
     574               0 :   if (base_win) {
     575               0 :     base_win->Destroy();
     576                 :   }
     577               0 :   mDocShell = nsnull;
     578               0 : }
     579                 : 
     580                 : static void
     581               0 : FirePageHideEvent(nsIDocShellTreeItem* aItem,
     582                 :                   nsIDOMEventTarget* aChromeEventHandler)
     583                 : {
     584               0 :   nsCOMPtr<nsIDOMDocument> doc = do_GetInterface(aItem);
     585               0 :   nsCOMPtr<nsIDocument> internalDoc = do_QueryInterface(doc);
     586               0 :   NS_ASSERTION(internalDoc, "What happened here?");
     587               0 :   internalDoc->OnPageHide(true, aChromeEventHandler);
     588                 : 
     589               0 :   PRInt32 childCount = 0;
     590               0 :   aItem->GetChildCount(&childCount);
     591               0 :   nsAutoTArray<nsCOMPtr<nsIDocShellTreeItem>, 8> kids;
     592               0 :   kids.AppendElements(childCount);
     593               0 :   for (PRInt32 i = 0; i < childCount; ++i) {
     594               0 :     aItem->GetChildAt(i, getter_AddRefs(kids[i]));
     595                 :   }
     596                 : 
     597               0 :   for (PRUint32 i = 0; i < kids.Length(); ++i) {
     598               0 :     if (kids[i]) {
     599               0 :       FirePageHideEvent(kids[i], aChromeEventHandler);
     600                 :     }
     601                 :   }
     602               0 : }
     603                 : 
     604                 : // The pageshow event is fired for a given document only if IsShowing() returns
     605                 : // the same thing as aFireIfShowing.  This gives us a way to fire pageshow only
     606                 : // on documents that are still loading or only on documents that are already
     607                 : // loaded.
     608                 : static void
     609               0 : FirePageShowEvent(nsIDocShellTreeItem* aItem,
     610                 :                   nsIDOMEventTarget* aChromeEventHandler,
     611                 :                   bool aFireIfShowing)
     612                 : {
     613               0 :   PRInt32 childCount = 0;
     614               0 :   aItem->GetChildCount(&childCount);
     615               0 :   nsAutoTArray<nsCOMPtr<nsIDocShellTreeItem>, 8> kids;
     616               0 :   kids.AppendElements(childCount);
     617               0 :   for (PRInt32 i = 0; i < childCount; ++i) {
     618               0 :     aItem->GetChildAt(i, getter_AddRefs(kids[i]));
     619                 :   }
     620                 : 
     621               0 :   for (PRUint32 i = 0; i < kids.Length(); ++i) {
     622               0 :     if (kids[i]) {
     623               0 :       FirePageShowEvent(kids[i], aChromeEventHandler, aFireIfShowing);
     624                 :     }
     625                 :   }
     626                 : 
     627               0 :   nsCOMPtr<nsIDOMDocument> doc = do_GetInterface(aItem);
     628               0 :   nsCOMPtr<nsIDocument> internalDoc = do_QueryInterface(doc);
     629               0 :   NS_ASSERTION(internalDoc, "What happened here?");
     630               0 :   if (internalDoc->IsShowing() == aFireIfShowing) {
     631               0 :     internalDoc->OnPageShow(true, aChromeEventHandler);
     632                 :   }
     633               0 : }
     634                 : 
     635                 : static void
     636               0 : SetTreeOwnerAndChromeEventHandlerOnDocshellTree(nsIDocShellTreeItem* aItem,
     637                 :                                                 nsIDocShellTreeOwner* aOwner,
     638                 :                                                 nsIDOMEventTarget* aHandler)
     639                 : {
     640               0 :   NS_PRECONDITION(aItem, "Must have item");
     641                 : 
     642               0 :   aItem->SetTreeOwner(aOwner);
     643               0 :   nsCOMPtr<nsIDocShell> shell(do_QueryInterface(aItem));
     644               0 :   shell->SetChromeEventHandler(aHandler);
     645                 : 
     646               0 :   PRInt32 childCount = 0;
     647               0 :   aItem->GetChildCount(&childCount);
     648               0 :   for (PRInt32 i = 0; i < childCount; ++i) {
     649               0 :     nsCOMPtr<nsIDocShellTreeItem> item;
     650               0 :     aItem->GetChildAt(i, getter_AddRefs(item));
     651               0 :     SetTreeOwnerAndChromeEventHandlerOnDocshellTree(item, aOwner, aHandler);
     652                 :   }
     653               0 : }
     654                 : 
     655                 : /**
     656                 :  * Set the type of the treeitem and hook it up to the treeowner.
     657                 :  * @param aItem the treeitem we're wrking working with
     658                 :  * @param aOwningContent the content node that owns aItem
     659                 :  * @param aTreeOwner the relevant treeowner; might be null
     660                 :  * @param aParentType the nsIDocShellTreeItem::GetType of our parent docshell
     661                 :  * @param aParentNode if non-null, the docshell we should be added as a child to
     662                 :  *
     663                 :  * @return whether aItem is top-level content
     664                 :  */
     665                 : static bool
     666               0 : AddTreeItemToTreeOwner(nsIDocShellTreeItem* aItem, nsIContent* aOwningContent,
     667                 :                        nsIDocShellTreeOwner* aOwner, PRInt32 aParentType,
     668                 :                        nsIDocShellTreeNode* aParentNode)
     669                 : {
     670               0 :   NS_PRECONDITION(aItem, "Must have docshell treeitem");
     671               0 :   NS_PRECONDITION(aOwningContent, "Must have owning content");
     672                 :   
     673               0 :   nsAutoString value;
     674               0 :   bool isContent = false;
     675                 : 
     676               0 :   if (aOwningContent->IsXUL()) {
     677               0 :       aOwningContent->GetAttr(kNameSpaceID_None, nsGkAtoms::type, value);
     678                 :   }
     679                 : 
     680                 :   // we accept "content" and "content-xxx" values.
     681                 :   // at time of writing, we expect "xxx" to be "primary" or "targetable", but
     682                 :   // someday it might be an integer expressing priority or something else.
     683                 : 
     684               0 :   isContent = value.LowerCaseEqualsLiteral("content") ||
     685               0 :     StringBeginsWith(value, NS_LITERAL_STRING("content-"),
     686               0 :                      nsCaseInsensitiveStringComparator());
     687                 : 
     688               0 :   if (isContent) {
     689                 :     // The web shell's type is content.
     690                 : 
     691               0 :     aItem->SetItemType(nsIDocShellTreeItem::typeContent);
     692                 :   } else {
     693                 :     // Inherit our type from our parent docshell.  If it is
     694                 :     // chrome, we'll be chrome.  If it is content, we'll be
     695                 :     // content.
     696                 : 
     697               0 :     aItem->SetItemType(aParentType);
     698                 :   }
     699                 : 
     700                 :   // Now that we have our type set, add ourselves to the parent, as needed.
     701               0 :   if (aParentNode) {
     702               0 :     aParentNode->AddChild(aItem);
     703                 :   }
     704                 : 
     705               0 :   bool retval = false;
     706               0 :   if (aParentType == nsIDocShellTreeItem::typeChrome && isContent) {
     707               0 :     retval = true;
     708                 : 
     709               0 :     bool is_primary = value.LowerCaseEqualsLiteral("content-primary");
     710                 : 
     711               0 :     if (aOwner) {
     712                 :       bool is_targetable = is_primary ||
     713               0 :         value.LowerCaseEqualsLiteral("content-targetable");
     714               0 :       aOwner->ContentShellAdded(aItem, is_primary, is_targetable, value);
     715                 :     }
     716                 :   }
     717                 : 
     718               0 :   return retval;
     719                 : }
     720                 : 
     721                 : static bool
     722               0 : AllDescendantsOfType(nsIDocShellTreeItem* aParentItem, PRInt32 aType)
     723                 : {
     724               0 :   PRInt32 childCount = 0;
     725               0 :   aParentItem->GetChildCount(&childCount);
     726                 : 
     727               0 :   for (PRInt32 i = 0; i < childCount; ++i) {
     728               0 :     nsCOMPtr<nsIDocShellTreeItem> kid;
     729               0 :     aParentItem->GetChildAt(i, getter_AddRefs(kid));
     730                 : 
     731                 :     PRInt32 kidType;
     732               0 :     kid->GetItemType(&kidType);
     733               0 :     if (kidType != aType || !AllDescendantsOfType(kid, aType)) {
     734               0 :       return false;
     735                 :     }
     736                 :   }
     737                 : 
     738               0 :   return true;
     739                 : }
     740                 : 
     741                 : /**
     742                 :  * A class that automatically sets mInShow to false when it goes
     743                 :  * out of scope.
     744                 :  */
     745                 : class NS_STACK_CLASS AutoResetInShow {
     746                 :   private:
     747                 :     nsFrameLoader* mFrameLoader;
     748                 :     MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
     749                 :   public:
     750               0 :     AutoResetInShow(nsFrameLoader* aFrameLoader MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
     751               0 :       : mFrameLoader(aFrameLoader)
     752                 :     {
     753               0 :       MOZ_GUARD_OBJECT_NOTIFIER_INIT;
     754               0 :     }
     755               0 :     ~AutoResetInShow() { mFrameLoader->mInShow = false; }
     756                 : };
     757                 : 
     758                 : 
     759                 : bool
     760               0 : nsFrameLoader::Show(PRInt32 marginWidth, PRInt32 marginHeight,
     761                 :                     PRInt32 scrollbarPrefX, PRInt32 scrollbarPrefY,
     762                 :                     nsSubDocumentFrame* frame)
     763                 : {
     764               0 :   if (mInShow) {
     765               0 :     return false;
     766                 :   }
     767                 :   // Reset mInShow if we exit early.
     768               0 :   AutoResetInShow resetInShow(this);
     769               0 :   mInShow = true;
     770                 : 
     771               0 :   nsresult rv = MaybeCreateDocShell();
     772               0 :   if (NS_FAILED(rv)) {
     773               0 :     return false;
     774                 :   }
     775                 : 
     776               0 :   if (!mRemoteFrame) {
     777               0 :     if (!mDocShell)
     778               0 :       return false;
     779               0 :     nsCOMPtr<nsIPresShell> presShell;
     780               0 :     mDocShell->GetPresShell(getter_AddRefs(presShell));
     781               0 :     if (presShell)
     782               0 :       return true;
     783                 : 
     784               0 :     mDocShell->SetMarginWidth(marginWidth);
     785               0 :     mDocShell->SetMarginHeight(marginHeight);
     786                 : 
     787               0 :     nsCOMPtr<nsIScrollable> sc = do_QueryInterface(mDocShell);
     788               0 :     if (sc) {
     789               0 :       sc->SetDefaultScrollbarPreferences(nsIScrollable::ScrollOrientation_X,
     790               0 :                                          scrollbarPrefX);
     791               0 :       sc->SetDefaultScrollbarPreferences(nsIScrollable::ScrollOrientation_Y,
     792               0 :                                          scrollbarPrefY);
     793                 :     }
     794                 :   }
     795                 : 
     796               0 :   nsIView* view = frame->EnsureInnerView();
     797               0 :   if (!view)
     798               0 :     return false;
     799                 : 
     800               0 :   if (mRemoteFrame) {
     801               0 :     return ShowRemoteFrame(GetSubDocumentSize(frame));
     802                 :   }
     803                 : 
     804               0 :   nsCOMPtr<nsIBaseWindow> baseWindow = do_QueryInterface(mDocShell);
     805               0 :   NS_ASSERTION(baseWindow, "Found a nsIDocShell that isn't a nsIBaseWindow.");
     806               0 :   nsIntSize size;
     807               0 :   if (!(frame->GetStateBits() & NS_FRAME_FIRST_REFLOW)) {
     808                 :     // We have a useful size already; use it, since we might get no
     809                 :     // more size updates.
     810               0 :     size = GetSubDocumentSize(frame);
     811                 :   } else {
     812                 :     // Pick some default size for now.  Using 10x10 because that's what the
     813                 :     // code here used to do.
     814               0 :     size.SizeTo(10, 10);
     815                 :   }
     816               0 :   baseWindow->InitWindow(nsnull, view->GetWidget(), 0, 0,
     817               0 :                          size.width, size.height);
     818                 :   // This is kinda whacky, this "Create()" call doesn't really
     819                 :   // create anything, one starts to wonder why this was named
     820                 :   // "Create"...
     821               0 :   baseWindow->Create();
     822               0 :   baseWindow->SetVisibility(true);
     823                 : 
     824                 :   // Trigger editor re-initialization if midas is turned on in the
     825                 :   // sub-document. This shouldn't be necessary, but given the way our
     826                 :   // editor works, it is. See
     827                 :   // https://bugzilla.mozilla.org/show_bug.cgi?id=284245
     828               0 :   nsCOMPtr<nsIPresShell> presShell;
     829               0 :   mDocShell->GetPresShell(getter_AddRefs(presShell));
     830               0 :   if (presShell) {
     831                 :     nsCOMPtr<nsIDOMHTMLDocument> doc =
     832               0 :       do_QueryInterface(presShell->GetDocument());
     833                 : 
     834               0 :     if (doc) {
     835               0 :       nsAutoString designMode;
     836               0 :       doc->GetDesignMode(designMode);
     837                 : 
     838               0 :       if (designMode.EqualsLiteral("on")) {
     839                 :         // Hold on to the editor object to let the document reattach to the
     840                 :         // same editor object, instead of creating a new one.
     841               0 :         nsCOMPtr<nsIEditorDocShell> editorDocshell = do_QueryInterface(mDocShell);
     842               0 :         nsCOMPtr<nsIEditor> editor;
     843               0 :         nsresult rv = editorDocshell->GetEditor(getter_AddRefs(editor));
     844               0 :         NS_ENSURE_SUCCESS(rv, false);
     845                 : 
     846               0 :         doc->SetDesignMode(NS_LITERAL_STRING("off"));
     847               0 :         doc->SetDesignMode(NS_LITERAL_STRING("on"));
     848                 :       } else {
     849                 :         // Re-initialize the presentation for contenteditable documents
     850               0 :         nsCOMPtr<nsIEditorDocShell> editorDocshell = do_QueryInterface(mDocShell);
     851               0 :         if (editorDocshell) {
     852               0 :           bool editable = false,
     853               0 :                  hasEditingSession = false;
     854               0 :           editorDocshell->GetEditable(&editable);
     855               0 :           editorDocshell->GetHasEditingSession(&hasEditingSession);
     856               0 :           nsCOMPtr<nsIEditor> editor;
     857               0 :           editorDocshell->GetEditor(getter_AddRefs(editor));
     858               0 :           if (editable && hasEditingSession && editor) {
     859               0 :             editor->PostCreate();
     860                 :           }
     861                 :         }
     862                 :       }
     863                 :     }
     864                 :   }
     865                 : 
     866               0 :   mInShow = false;
     867               0 :   if (mHideCalled) {
     868               0 :     mHideCalled = false;
     869               0 :     Hide();
     870               0 :     return false;
     871                 :   }
     872               0 :   return true;
     873                 : }
     874                 : 
     875                 : void
     876               0 : nsFrameLoader::MarginsChanged(PRUint32 aMarginWidth,
     877                 :                               PRUint32 aMarginHeight)
     878                 : {
     879                 :   // We assume that the margins are always zero for remote frames.
     880               0 :   if (mRemoteFrame)
     881               0 :     return;
     882                 : 
     883                 :   // If there's no docshell, we're probably not up and running yet.
     884                 :   // nsFrameLoader::Show() will take care of setting the right
     885                 :   // margins.
     886               0 :   if (!mDocShell)
     887               0 :     return;
     888                 : 
     889                 :   // Set the margins
     890               0 :   mDocShell->SetMarginWidth(aMarginWidth);
     891               0 :   mDocShell->SetMarginHeight(aMarginHeight);
     892                 : 
     893                 :   // Trigger a restyle if there's a prescontext
     894               0 :   nsRefPtr<nsPresContext> presContext;
     895               0 :   mDocShell->GetPresContext(getter_AddRefs(presContext));
     896               0 :   if (presContext)
     897               0 :     presContext->RebuildAllStyleData(nsChangeHint(0));
     898                 : }
     899                 : 
     900                 : bool
     901               0 : nsFrameLoader::ShowRemoteFrame(const nsIntSize& size)
     902                 : {
     903               0 :   NS_ASSERTION(mRemoteFrame, "ShowRemote only makes sense on remote frames.");
     904                 : 
     905               0 :   if (!mRemoteBrowser) {
     906               0 :     TryRemoteBrowser();
     907                 : 
     908               0 :     if (!mRemoteBrowser) {
     909               0 :       NS_ERROR("Couldn't create child process.");
     910               0 :       return false;
     911                 :     }
     912                 :   }
     913                 : 
     914                 :   // FIXME/bug 589337: Show()/Hide() is pretty expensive for
     915                 :   // cross-process layers; need to figure out what behavior we really
     916                 :   // want here.  For now, hack.
     917               0 :   if (!mRemoteBrowserShown) {
     918               0 :     mRemoteBrowser->Show(size);
     919               0 :     mRemoteBrowserShown = true;
     920                 : 
     921               0 :     EnsureMessageManager();
     922                 :   } else {
     923               0 :     nsRect dimensions;
     924               0 :     NS_ENSURE_SUCCESS(GetWindowDimensions(dimensions), false);
     925               0 :     mRemoteBrowser->UpdateDimensions(dimensions, size);
     926                 :   }
     927                 : 
     928               0 :   return true;
     929                 : }
     930                 : 
     931                 : void
     932               0 : nsFrameLoader::Hide()
     933                 : {
     934               0 :   if (mHideCalled) {
     935               0 :     return;
     936                 :   }
     937               0 :   if (mInShow) {
     938               0 :     mHideCalled = true;
     939               0 :     return;
     940                 :   }
     941                 : 
     942               0 :   if (!mDocShell)
     943               0 :     return;
     944                 : 
     945               0 :   nsCOMPtr<nsIContentViewer> contentViewer;
     946               0 :   mDocShell->GetContentViewer(getter_AddRefs(contentViewer));
     947               0 :   if (contentViewer)
     948               0 :     contentViewer->SetSticky(false);
     949                 : 
     950               0 :   nsCOMPtr<nsIBaseWindow> baseWin = do_QueryInterface(mDocShell);
     951               0 :   NS_ASSERTION(baseWin,
     952                 :                "Found an nsIDocShell which doesn't implement nsIBaseWindow.");
     953               0 :   baseWin->SetVisibility(false);
     954               0 :   baseWin->SetParentWidget(nsnull);
     955                 : }
     956                 : 
     957                 : nsresult
     958               0 : nsFrameLoader::SwapWithOtherLoader(nsFrameLoader* aOther,
     959                 :                                    nsRefPtr<nsFrameLoader>& aFirstToSwap,
     960                 :                                    nsRefPtr<nsFrameLoader>& aSecondToSwap)
     961                 : {
     962               0 :   NS_PRECONDITION((aFirstToSwap == this && aSecondToSwap == aOther) ||
     963                 :                   (aFirstToSwap == aOther && aSecondToSwap == this),
     964                 :                   "Swapping some sort of random loaders?");
     965               0 :   NS_ENSURE_STATE(!mInShow && !aOther->mInShow);
     966                 : 
     967               0 :   Element* ourContent = mOwnerContent;
     968               0 :   Element* otherContent = aOther->mOwnerContent;
     969                 : 
     970               0 :   if (!ourContent || !otherContent) {
     971                 :     // Can't handle this
     972               0 :     return NS_ERROR_NOT_IMPLEMENTED;
     973                 :   }
     974                 : 
     975                 :   // Make sure there are no same-origin issues
     976                 :   bool equal;
     977                 :   nsresult rv =
     978               0 :     ourContent->NodePrincipal()->Equals(otherContent->NodePrincipal(), &equal);
     979               0 :   if (NS_FAILED(rv) || !equal) {
     980                 :     // Security problems loom.  Just bail on it all
     981               0 :     return NS_ERROR_DOM_SECURITY_ERR;
     982                 :   }
     983                 : 
     984               0 :   nsCOMPtr<nsIDocShell> ourDocshell = GetExistingDocShell();
     985               0 :   nsCOMPtr<nsIDocShell> otherDocshell = aOther->GetExistingDocShell();
     986               0 :   if (!ourDocshell || !otherDocshell) {
     987                 :     // How odd
     988               0 :     return NS_ERROR_NOT_IMPLEMENTED;
     989                 :   }
     990                 : 
     991                 :   // To avoid having to mess with session history, avoid swapping
     992                 :   // frameloaders that don't correspond to root same-type docshells,
     993                 :   // unless both roots have session history disabled.
     994               0 :   nsCOMPtr<nsIDocShellTreeItem> ourTreeItem = do_QueryInterface(ourDocshell);
     995                 :   nsCOMPtr<nsIDocShellTreeItem> otherTreeItem =
     996               0 :     do_QueryInterface(otherDocshell);
     997               0 :   nsCOMPtr<nsIDocShellTreeItem> ourRootTreeItem, otherRootTreeItem;
     998               0 :   ourTreeItem->GetSameTypeRootTreeItem(getter_AddRefs(ourRootTreeItem));
     999               0 :   otherTreeItem->GetSameTypeRootTreeItem(getter_AddRefs(otherRootTreeItem));
    1000                 :   nsCOMPtr<nsIWebNavigation> ourRootWebnav =
    1001               0 :     do_QueryInterface(ourRootTreeItem);
    1002                 :   nsCOMPtr<nsIWebNavigation> otherRootWebnav =
    1003               0 :     do_QueryInterface(otherRootTreeItem);
    1004                 : 
    1005               0 :   if (!ourRootWebnav || !otherRootWebnav) {
    1006               0 :     return NS_ERROR_NOT_IMPLEMENTED;
    1007                 :   }
    1008                 : 
    1009               0 :   nsCOMPtr<nsISHistory> ourHistory;
    1010               0 :   nsCOMPtr<nsISHistory> otherHistory;
    1011               0 :   ourRootWebnav->GetSessionHistory(getter_AddRefs(ourHistory));
    1012               0 :   otherRootWebnav->GetSessionHistory(getter_AddRefs(otherHistory));
    1013                 : 
    1014               0 :   if ((ourRootTreeItem != ourTreeItem || otherRootTreeItem != otherTreeItem) &&
    1015               0 :       (ourHistory || otherHistory)) {
    1016               0 :     return NS_ERROR_NOT_IMPLEMENTED;
    1017                 :   }
    1018                 : 
    1019                 :   // Also make sure that the two docshells are the same type. Otherwise
    1020                 :   // swapping is certainly not safe.
    1021               0 :   PRInt32 ourType = nsIDocShellTreeItem::typeChrome;
    1022               0 :   PRInt32 otherType = nsIDocShellTreeItem::typeChrome;
    1023               0 :   ourTreeItem->GetItemType(&ourType);
    1024               0 :   otherTreeItem->GetItemType(&otherType);
    1025               0 :   if (ourType != otherType) {
    1026               0 :     return NS_ERROR_NOT_IMPLEMENTED;
    1027                 :   }
    1028                 : 
    1029                 :   // One more twist here.  Setting up the right treeowners in a heterogeneous
    1030                 :   // tree is a bit of a pain.  So make sure that if ourType is not
    1031                 :   // nsIDocShellTreeItem::typeContent then all of our descendants are the same
    1032                 :   // type as us.
    1033               0 :   if (ourType != nsIDocShellTreeItem::typeContent &&
    1034               0 :       (!AllDescendantsOfType(ourTreeItem, ourType) ||
    1035               0 :        !AllDescendantsOfType(otherTreeItem, otherType))) {
    1036               0 :     return NS_ERROR_NOT_IMPLEMENTED;
    1037                 :   }
    1038                 :   
    1039                 :   // Save off the tree owners, frame elements, chrome event handlers, and
    1040                 :   // docshell and document parents before doing anything else.
    1041               0 :   nsCOMPtr<nsIDocShellTreeOwner> ourOwner, otherOwner;
    1042               0 :   ourTreeItem->GetTreeOwner(getter_AddRefs(ourOwner));
    1043               0 :   otherTreeItem->GetTreeOwner(getter_AddRefs(otherOwner));
    1044                 :   // Note: it's OK to have null treeowners.
    1045                 : 
    1046               0 :   nsCOMPtr<nsIDocShellTreeItem> ourParentItem, otherParentItem;
    1047               0 :   ourTreeItem->GetParent(getter_AddRefs(ourParentItem));
    1048               0 :   otherTreeItem->GetParent(getter_AddRefs(otherParentItem));
    1049               0 :   if (!ourParentItem || !otherParentItem) {
    1050               0 :     return NS_ERROR_NOT_IMPLEMENTED;
    1051                 :   }
    1052                 : 
    1053                 :   // Make sure our parents are the same type too
    1054               0 :   PRInt32 ourParentType = nsIDocShellTreeItem::typeContent;
    1055               0 :   PRInt32 otherParentType = nsIDocShellTreeItem::typeContent;
    1056               0 :   ourParentItem->GetItemType(&ourParentType);
    1057               0 :   otherParentItem->GetItemType(&otherParentType);
    1058               0 :   if (ourParentType != otherParentType) {
    1059               0 :     return NS_ERROR_NOT_IMPLEMENTED;
    1060                 :   }
    1061                 : 
    1062               0 :   nsCOMPtr<nsPIDOMWindow> ourWindow = do_GetInterface(ourDocshell);
    1063               0 :   nsCOMPtr<nsPIDOMWindow> otherWindow = do_GetInterface(otherDocshell);
    1064                 : 
    1065                 :   nsCOMPtr<nsIDOMElement> ourFrameElement =
    1066               0 :     ourWindow->GetFrameElementInternal();
    1067                 :   nsCOMPtr<nsIDOMElement> otherFrameElement =
    1068               0 :     otherWindow->GetFrameElementInternal();
    1069                 : 
    1070                 :   nsCOMPtr<nsIDOMEventTarget> ourChromeEventHandler =
    1071               0 :     do_QueryInterface(ourWindow->GetChromeEventHandler());
    1072                 :   nsCOMPtr<nsIDOMEventTarget> otherChromeEventHandler =
    1073               0 :     do_QueryInterface(otherWindow->GetChromeEventHandler());
    1074                 : 
    1075               0 :   NS_ASSERTION(SameCOMIdentity(ourFrameElement, ourContent) &&
    1076                 :                SameCOMIdentity(otherFrameElement, otherContent) &&
    1077                 :                SameCOMIdentity(ourChromeEventHandler, ourContent) &&
    1078                 :                SameCOMIdentity(otherChromeEventHandler, otherContent),
    1079                 :                "How did that happen, exactly?");
    1080                 : 
    1081                 :   nsCOMPtr<nsIDocument> ourChildDocument =
    1082               0 :     do_QueryInterface(ourWindow->GetExtantDocument());
    1083                 :   nsCOMPtr<nsIDocument> otherChildDocument =
    1084               0 :     do_QueryInterface(otherWindow->GetExtantDocument());
    1085               0 :   if (!ourChildDocument || !otherChildDocument) {
    1086                 :     // This shouldn't be happening
    1087               0 :     return NS_ERROR_NOT_IMPLEMENTED;
    1088                 :   }
    1089                 : 
    1090                 :   nsCOMPtr<nsIDocument> ourParentDocument =
    1091               0 :     ourChildDocument->GetParentDocument();
    1092                 :   nsCOMPtr<nsIDocument> otherParentDocument =
    1093               0 :     otherChildDocument->GetParentDocument();
    1094                 : 
    1095                 :   // Make sure to swap docshells between the two frames.
    1096               0 :   nsIDocument* ourDoc = ourContent->GetCurrentDoc();
    1097               0 :   nsIDocument* otherDoc = otherContent->GetCurrentDoc();
    1098               0 :   if (!ourDoc || !otherDoc) {
    1099                 :     // Again, how odd, given that we had docshells
    1100               0 :     return NS_ERROR_NOT_IMPLEMENTED;
    1101                 :   }
    1102                 : 
    1103               0 :   NS_ASSERTION(ourDoc == ourParentDocument, "Unexpected parent document");
    1104               0 :   NS_ASSERTION(otherDoc == otherParentDocument, "Unexpected parent document");
    1105                 : 
    1106               0 :   nsIPresShell* ourShell = ourDoc->GetShell();
    1107               0 :   nsIPresShell* otherShell = otherDoc->GetShell();
    1108               0 :   if (!ourShell || !otherShell) {
    1109               0 :     return NS_ERROR_NOT_IMPLEMENTED;
    1110                 :   }
    1111                 : 
    1112               0 :   bool weAreBrowserFrame = false;
    1113               0 :   bool otherIsBrowserFrame = false;
    1114               0 :   ourDocshell->GetIsBrowserFrame(&weAreBrowserFrame);
    1115               0 :   otherDocshell->GetIsBrowserFrame(&otherIsBrowserFrame);
    1116               0 :   if (weAreBrowserFrame != otherIsBrowserFrame) {
    1117               0 :     return NS_ERROR_NOT_IMPLEMENTED;
    1118                 :   }
    1119                 : 
    1120               0 :   if (mInSwap || aOther->mInSwap) {
    1121               0 :     return NS_ERROR_NOT_IMPLEMENTED;
    1122                 :   }
    1123               0 :   mInSwap = aOther->mInSwap = true;
    1124                 : 
    1125                 :   // Fire pageshow events on still-loading pages, and then fire pagehide
    1126                 :   // events.  Note that we do NOT fire these in the normal way, but just fire
    1127                 :   // them on the chrome event handlers.
    1128               0 :   FirePageShowEvent(ourTreeItem, ourChromeEventHandler, false);
    1129               0 :   FirePageShowEvent(otherTreeItem, otherChromeEventHandler, false);
    1130               0 :   FirePageHideEvent(ourTreeItem, ourChromeEventHandler);
    1131               0 :   FirePageHideEvent(otherTreeItem, otherChromeEventHandler);
    1132                 :   
    1133               0 :   nsIFrame* ourFrame = ourContent->GetPrimaryFrame();
    1134               0 :   nsIFrame* otherFrame = otherContent->GetPrimaryFrame();
    1135               0 :   if (!ourFrame || !otherFrame) {
    1136               0 :     mInSwap = aOther->mInSwap = false;
    1137               0 :     FirePageShowEvent(ourTreeItem, ourChromeEventHandler, true);
    1138               0 :     FirePageShowEvent(otherTreeItem, otherChromeEventHandler, true);
    1139               0 :     return NS_ERROR_NOT_IMPLEMENTED;
    1140                 :   }
    1141                 : 
    1142               0 :   nsSubDocumentFrame* ourFrameFrame = do_QueryFrame(ourFrame);
    1143               0 :   if (!ourFrameFrame) {
    1144               0 :     mInSwap = aOther->mInSwap = false;
    1145               0 :     FirePageShowEvent(ourTreeItem, ourChromeEventHandler, true);
    1146               0 :     FirePageShowEvent(otherTreeItem, otherChromeEventHandler, true);
    1147               0 :     return NS_ERROR_NOT_IMPLEMENTED;
    1148                 :   }
    1149                 : 
    1150                 :   // OK.  First begin to swap the docshells in the two nsIFrames
    1151               0 :   rv = ourFrameFrame->BeginSwapDocShells(otherFrame);
    1152               0 :   if (NS_FAILED(rv)) {
    1153               0 :     mInSwap = aOther->mInSwap = false;
    1154               0 :     FirePageShowEvent(ourTreeItem, ourChromeEventHandler, true);
    1155               0 :     FirePageShowEvent(otherTreeItem, otherChromeEventHandler, true);
    1156               0 :     return rv;
    1157                 :   }
    1158                 : 
    1159                 :   // Now move the docshells to the right docshell trees.  Note that this
    1160                 :   // resets their treeowners to null.
    1161               0 :   ourParentItem->RemoveChild(ourTreeItem);
    1162               0 :   otherParentItem->RemoveChild(otherTreeItem);
    1163               0 :   if (ourType == nsIDocShellTreeItem::typeContent) {
    1164               0 :     ourOwner->ContentShellRemoved(ourTreeItem);
    1165               0 :     otherOwner->ContentShellRemoved(otherTreeItem);
    1166                 :   }
    1167                 :   
    1168               0 :   ourParentItem->AddChild(otherTreeItem);
    1169               0 :   otherParentItem->AddChild(ourTreeItem);
    1170                 : 
    1171                 :   // Restore the correct treeowners
    1172                 :   SetTreeOwnerAndChromeEventHandlerOnDocshellTree(ourTreeItem, otherOwner,
    1173               0 :                                                   otherChromeEventHandler);
    1174                 :   SetTreeOwnerAndChromeEventHandlerOnDocshellTree(otherTreeItem, ourOwner,
    1175               0 :                                                   ourChromeEventHandler);
    1176                 : 
    1177                 :   AddTreeItemToTreeOwner(ourTreeItem, otherContent, otherOwner,
    1178               0 :                          otherParentType, nsnull);
    1179                 :   AddTreeItemToTreeOwner(otherTreeItem, ourContent, ourOwner, ourParentType,
    1180               0 :                          nsnull);
    1181                 : 
    1182                 :   // SetSubDocumentFor nulls out parent documents on the old child doc if a
    1183                 :   // new non-null document is passed in, so just go ahead and remove both
    1184                 :   // kids before reinserting in the parent subdoc maps, to avoid
    1185                 :   // complications.
    1186               0 :   ourParentDocument->SetSubDocumentFor(ourContent, nsnull);
    1187               0 :   otherParentDocument->SetSubDocumentFor(otherContent, nsnull);
    1188               0 :   ourParentDocument->SetSubDocumentFor(ourContent, otherChildDocument);
    1189               0 :   otherParentDocument->SetSubDocumentFor(otherContent, ourChildDocument);
    1190                 : 
    1191               0 :   ourWindow->SetFrameElementInternal(otherFrameElement);
    1192               0 :   otherWindow->SetFrameElementInternal(ourFrameElement);
    1193                 : 
    1194               0 :   SetOwnerContent(otherContent);
    1195               0 :   aOther->SetOwnerContent(ourContent);
    1196                 : 
    1197               0 :   nsRefPtr<nsFrameMessageManager> ourMessageManager = mMessageManager;
    1198               0 :   nsRefPtr<nsFrameMessageManager> otherMessageManager = aOther->mMessageManager;
    1199                 :   // Swap pointers in child message managers.
    1200               0 :   if (mChildMessageManager) {
    1201                 :     nsInProcessTabChildGlobal* tabChild =
    1202               0 :       static_cast<nsInProcessTabChildGlobal*>(mChildMessageManager.get());
    1203               0 :     tabChild->SetOwner(otherContent);
    1204               0 :     tabChild->SetChromeMessageManager(otherMessageManager);
    1205                 :   }
    1206               0 :   if (aOther->mChildMessageManager) {
    1207                 :     nsInProcessTabChildGlobal* otherTabChild =
    1208               0 :       static_cast<nsInProcessTabChildGlobal*>(aOther->mChildMessageManager.get());
    1209               0 :     otherTabChild->SetOwner(ourContent);
    1210               0 :     otherTabChild->SetChromeMessageManager(ourMessageManager);
    1211                 :   }
    1212                 :   // Swap and setup things in parent message managers.
    1213                 :   nsFrameMessageManager* ourParentManager = mMessageManager ?
    1214               0 :     mMessageManager->GetParentManager() : nsnull;
    1215                 :   nsFrameMessageManager* otherParentManager = aOther->mMessageManager ?
    1216               0 :     aOther->mMessageManager->GetParentManager() : nsnull;
    1217                 :   JSContext* thisCx =
    1218               0 :     mMessageManager ? mMessageManager->GetJSContext() : nsnull;
    1219                 :   JSContext* otherCx = 
    1220               0 :     aOther->mMessageManager ? aOther->mMessageManager->GetJSContext() : nsnull;
    1221               0 :   if (mMessageManager) {
    1222               0 :     mMessageManager->RemoveFromParent();
    1223               0 :     mMessageManager->SetJSContext(otherCx);
    1224               0 :     mMessageManager->SetParentManager(otherParentManager);
    1225               0 :     mMessageManager->SetCallbackData(aOther, false);
    1226                 :   }
    1227               0 :   if (aOther->mMessageManager) {
    1228               0 :     aOther->mMessageManager->RemoveFromParent();
    1229               0 :     aOther->mMessageManager->SetJSContext(thisCx);
    1230               0 :     aOther->mMessageManager->SetParentManager(ourParentManager);
    1231               0 :     aOther->mMessageManager->SetCallbackData(this, false);
    1232                 :   }
    1233               0 :   mMessageManager.swap(aOther->mMessageManager);
    1234                 : 
    1235               0 :   aFirstToSwap.swap(aSecondToSwap);
    1236                 : 
    1237                 :   // Drop any cached content viewers in the two session histories.
    1238                 :   nsCOMPtr<nsISHistoryInternal> ourInternalHistory =
    1239               0 :     do_QueryInterface(ourHistory);
    1240                 :   nsCOMPtr<nsISHistoryInternal> otherInternalHistory =
    1241               0 :     do_QueryInterface(otherHistory);
    1242               0 :   if (ourInternalHistory) {
    1243               0 :     ourInternalHistory->EvictAllContentViewers();
    1244                 :   }
    1245               0 :   if (otherInternalHistory) {
    1246               0 :     otherInternalHistory->EvictAllContentViewers();
    1247                 :   }
    1248                 : 
    1249               0 :   NS_ASSERTION(ourFrame == ourContent->GetPrimaryFrame() &&
    1250                 :                otherFrame == otherContent->GetPrimaryFrame(),
    1251                 :                "changed primary frame");
    1252                 : 
    1253               0 :   ourFrameFrame->EndSwapDocShells(otherFrame);
    1254                 : 
    1255               0 :   ourParentDocument->FlushPendingNotifications(Flush_Layout);
    1256               0 :   otherParentDocument->FlushPendingNotifications(Flush_Layout);
    1257                 : 
    1258               0 :   FirePageShowEvent(ourTreeItem, otherChromeEventHandler, true);
    1259               0 :   FirePageShowEvent(otherTreeItem, ourChromeEventHandler, true);
    1260                 : 
    1261               0 :   mInSwap = aOther->mInSwap = false;
    1262               0 :   return NS_OK;
    1263                 : }
    1264                 : 
    1265                 : void
    1266               0 : nsFrameLoader::DestroyChild()
    1267                 : {
    1268               0 :   if (mRemoteBrowser) {
    1269               0 :     mRemoteBrowser->SetOwnerElement(nsnull);
    1270               0 :     mRemoteBrowser->Destroy();
    1271               0 :     mRemoteBrowser = nsnull;
    1272                 :   }
    1273               0 : }
    1274                 : 
    1275                 : NS_IMETHODIMP
    1276               0 : nsFrameLoader::Destroy()
    1277                 : {
    1278               0 :   if (mDestroyCalled) {
    1279               0 :     return NS_OK;
    1280                 :   }
    1281               0 :   mDestroyCalled = true;
    1282                 : 
    1283               0 :   if (mMessageManager) {
    1284               0 :     mMessageManager->Disconnect();
    1285                 :   }
    1286               0 :   if (mChildMessageManager) {
    1287               0 :     static_cast<nsInProcessTabChildGlobal*>(mChildMessageManager.get())->Disconnect();
    1288                 :   }
    1289                 : 
    1290               0 :   nsCOMPtr<nsIDocument> doc;
    1291               0 :   bool dynamicSubframeRemoval = false;
    1292               0 :   if (mOwnerContent) {
    1293               0 :     doc = mOwnerContent->OwnerDoc();
    1294               0 :     dynamicSubframeRemoval = !mIsTopLevelContent && !doc->InUnlinkOrDeletion();
    1295               0 :     doc->SetSubDocumentFor(mOwnerContent, nsnull);
    1296                 : 
    1297               0 :     SetOwnerContent(nsnull);
    1298                 :   }
    1299               0 :   DestroyChild();
    1300                 : 
    1301                 :   // Seems like this is a dynamic frame removal.
    1302               0 :   if (dynamicSubframeRemoval) {
    1303               0 :     nsCOMPtr<nsIDocShellHistory> dhistory = do_QueryInterface(mDocShell);
    1304               0 :     if (dhistory) {
    1305               0 :       dhistory->RemoveFromSessionHistory();
    1306                 :     }
    1307                 :   }
    1308                 : 
    1309                 :   // Let the tree owner know we're gone.
    1310               0 :   if (mIsTopLevelContent) {
    1311               0 :     nsCOMPtr<nsIDocShellTreeItem> ourItem = do_QueryInterface(mDocShell);
    1312               0 :     if (ourItem) {
    1313               0 :       nsCOMPtr<nsIDocShellTreeItem> parentItem;
    1314               0 :       ourItem->GetParent(getter_AddRefs(parentItem));
    1315               0 :       nsCOMPtr<nsIDocShellTreeOwner> owner = do_GetInterface(parentItem);
    1316               0 :       if (owner) {
    1317               0 :         owner->ContentShellRemoved(ourItem);
    1318                 :       }
    1319                 :     }
    1320                 :   }
    1321                 :   
    1322                 :   // Let our window know that we are gone
    1323               0 :   nsCOMPtr<nsPIDOMWindow> win_private(do_GetInterface(mDocShell));
    1324               0 :   if (win_private) {
    1325               0 :     win_private->SetFrameElementInternal(nsnull);
    1326                 :   }
    1327                 : 
    1328               0 :   if ((mNeedsAsyncDestroy || !doc ||
    1329               0 :        NS_FAILED(doc->FinalizeFrameLoader(this))) && mDocShell) {
    1330               0 :     nsCOMPtr<nsIRunnable> event = new nsAsyncDocShellDestroyer(mDocShell);
    1331               0 :     NS_ENSURE_TRUE(event, NS_ERROR_OUT_OF_MEMORY);
    1332               0 :     NS_DispatchToCurrentThread(event);
    1333                 : 
    1334                 :     // Let go of our docshell now that the async destroyer holds on to
    1335                 :     // the docshell.
    1336                 : 
    1337               0 :     mDocShell = nsnull;
    1338                 :   }
    1339                 : 
    1340                 :   // NOTE: 'this' may very well be gone by now.
    1341                 : 
    1342               0 :   return NS_OK;
    1343                 : }
    1344                 : 
    1345                 : NS_IMETHODIMP
    1346               0 : nsFrameLoader::GetDepthTooGreat(bool* aDepthTooGreat)
    1347                 : {
    1348               0 :   *aDepthTooGreat = mDepthTooGreat;
    1349               0 :   return NS_OK;
    1350                 : }
    1351                 : 
    1352                 : void
    1353               0 : nsFrameLoader::SetOwnerContent(Element* aContent)
    1354                 : {
    1355               0 :   mOwnerContent = aContent;
    1356               0 :   if (RenderFrameParent* rfp = GetCurrentRemoteFrame()) {
    1357               0 :     rfp->OwnerContentChanged(aContent);
    1358                 :   }
    1359               0 : }
    1360                 : 
    1361                 : bool
    1362               0 : nsFrameLoader::ShouldUseRemoteProcess()
    1363                 : {
    1364                 :   // Check for *disabled* multi-process first: environment, pref
    1365                 :   // Then check for *enabled* multi-process attribute
    1366                 :   // Default is not-remote.
    1367                 : 
    1368               0 :   if (PR_GetEnv("MOZ_DISABLE_OOP_TABS") ||
    1369               0 :       Preferences::GetBool("dom.ipc.tabs.disabled", false)) {
    1370               0 :     return false;
    1371                 :   }
    1372                 : 
    1373                 :   return (bool) mOwnerContent->AttrValueIs(kNameSpaceID_None,
    1374                 :                                            nsGkAtoms::Remote,
    1375                 :                                            nsGkAtoms::_true,
    1376               0 :                                            eCaseMatters);
    1377                 : }
    1378                 : 
    1379                 : nsresult
    1380               0 : nsFrameLoader::MaybeCreateDocShell()
    1381                 : {
    1382               0 :   if (mDocShell) {
    1383               0 :     return NS_OK;
    1384                 :   }
    1385               0 :   if (mRemoteFrame) {
    1386               0 :     return NS_OK;
    1387                 :   }
    1388               0 :   NS_ENSURE_STATE(!mDestroyCalled);
    1389                 : 
    1390               0 :   if (ShouldUseRemoteProcess()) {
    1391               0 :     mRemoteFrame = true;
    1392               0 :     return NS_OK;
    1393                 :   }
    1394                 : 
    1395                 :   // Get our parent docshell off the document of mOwnerContent
    1396                 :   // XXXbz this is such a total hack.... We really need to have a
    1397                 :   // better setup for doing this.
    1398               0 :   nsIDocument* doc = mOwnerContent->OwnerDoc();
    1399               0 :   if (!(doc->IsStaticDocument() || mOwnerContent->IsInDoc())) {
    1400               0 :     return NS_ERROR_UNEXPECTED;
    1401                 :   }
    1402                 : 
    1403               0 :   if (doc->IsResourceDoc() || !doc->IsActive()) {
    1404                 :     // Don't allow subframe loads in resource documents, nor
    1405                 :     // in non-active documents.
    1406               0 :     return NS_ERROR_NOT_AVAILABLE;
    1407                 :   }
    1408                 : 
    1409                 :   nsCOMPtr<nsISupports> container =
    1410               0 :     doc->GetContainer();
    1411               0 :   nsCOMPtr<nsIWebNavigation> parentAsWebNav = do_QueryInterface(container);
    1412               0 :   NS_ENSURE_STATE(parentAsWebNav);
    1413                 : 
    1414                 :   // Create the docshell...
    1415               0 :   mDocShell = do_CreateInstance("@mozilla.org/docshell;1");
    1416               0 :   NS_ENSURE_TRUE(mDocShell, NS_ERROR_FAILURE);
    1417                 : 
    1418               0 :   if (!mNetworkCreated) {
    1419               0 :     nsCOMPtr<nsIDocShellHistory> history = do_QueryInterface(mDocShell);
    1420               0 :     if (history) {
    1421               0 :       history->SetCreatedDynamically(true);
    1422                 :     }
    1423                 :   }
    1424                 : 
    1425                 :   // Get the frame name and tell the docshell about it.
    1426               0 :   nsCOMPtr<nsIDocShellTreeItem> docShellAsItem(do_QueryInterface(mDocShell));
    1427               0 :   NS_ENSURE_TRUE(docShellAsItem, NS_ERROR_FAILURE);
    1428               0 :   nsAutoString frameName;
    1429                 : 
    1430               0 :   PRInt32 namespaceID = mOwnerContent->GetNameSpaceID();
    1431               0 :   if (namespaceID == kNameSpaceID_XHTML && !mOwnerContent->IsInHTMLDocument()) {
    1432               0 :     mOwnerContent->GetAttr(kNameSpaceID_None, nsGkAtoms::id, frameName);
    1433                 :   } else {
    1434               0 :     mOwnerContent->GetAttr(kNameSpaceID_None, nsGkAtoms::name, frameName);
    1435                 :     // XXX if no NAME then use ID, after a transition period this will be
    1436                 :     // changed so that XUL only uses ID too (bug 254284).
    1437               0 :     if (frameName.IsEmpty() && namespaceID == kNameSpaceID_XUL) {
    1438               0 :       mOwnerContent->GetAttr(kNameSpaceID_None, nsGkAtoms::id, frameName);
    1439                 :     }
    1440                 :   }
    1441                 : 
    1442               0 :   if (!frameName.IsEmpty()) {
    1443               0 :     docShellAsItem->SetName(frameName.get());
    1444                 :   }
    1445                 : 
    1446                 :   // If our container is a web-shell, inform it that it has a new
    1447                 :   // child. If it's not a web-shell then some things will not operate
    1448                 :   // properly.
    1449                 : 
    1450               0 :   nsCOMPtr<nsIDocShellTreeNode> parentAsNode(do_QueryInterface(parentAsWebNav));
    1451               0 :   if (parentAsNode) {
    1452                 :     // Note: This logic duplicates a lot of logic in
    1453                 :     // nsSubDocumentFrame::AttributeChanged.  We should fix that.
    1454                 : 
    1455                 :     nsCOMPtr<nsIDocShellTreeItem> parentAsItem =
    1456               0 :       do_QueryInterface(parentAsNode);
    1457                 : 
    1458                 :     PRInt32 parentType;
    1459               0 :     parentAsItem->GetItemType(&parentType);
    1460                 : 
    1461                 :     // XXXbz why is this in content code, exactly?  We should handle
    1462                 :     // this some other way.....  Not sure how yet.
    1463               0 :     nsCOMPtr<nsIDocShellTreeOwner> parentTreeOwner;
    1464               0 :     parentAsItem->GetTreeOwner(getter_AddRefs(parentTreeOwner));
    1465               0 :     NS_ENSURE_STATE(parentTreeOwner);
    1466                 :     mIsTopLevelContent =
    1467                 :       AddTreeItemToTreeOwner(docShellAsItem, mOwnerContent, parentTreeOwner,
    1468               0 :                              parentType, parentAsNode);
    1469                 : 
    1470                 :     // Make sure all shells have links back to the content element
    1471                 :     // in the nearest enclosing chrome shell.
    1472               0 :     nsCOMPtr<nsIDOMEventTarget> chromeEventHandler;
    1473                 : 
    1474               0 :     if (parentType == nsIDocShellTreeItem::typeChrome) {
    1475                 :       // Our parent shell is a chrome shell. It is therefore our nearest
    1476                 :       // enclosing chrome shell.
    1477                 : 
    1478               0 :       chromeEventHandler = do_QueryInterface(mOwnerContent);
    1479               0 :       NS_ASSERTION(chromeEventHandler,
    1480                 :                    "This mContent should implement this.");
    1481                 :     } else {
    1482               0 :       nsCOMPtr<nsIDocShell> parentShell(do_QueryInterface(parentAsNode));
    1483                 : 
    1484                 :       // Our parent shell is a content shell. Get the chrome event
    1485                 :       // handler from it and use that for our shell as well.
    1486                 : 
    1487               0 :       parentShell->GetChromeEventHandler(getter_AddRefs(chromeEventHandler));
    1488                 :     }
    1489                 : 
    1490               0 :     mDocShell->SetChromeEventHandler(chromeEventHandler);
    1491                 :   }
    1492                 : 
    1493               0 :   nsCOMPtr<nsIMozBrowserFrame> browserFrame = do_QueryInterface(mOwnerContent);
    1494               0 :   if (browserFrame) {
    1495               0 :     bool isBrowserFrame = false;
    1496               0 :     browserFrame->GetReallyIsBrowser(&isBrowserFrame);
    1497               0 :     mDocShell->SetIsBrowserFrame(isBrowserFrame);
    1498                 :   }
    1499                 : 
    1500                 :   // This is nasty, this code (the do_GetInterface(mDocShell) below)
    1501                 :   // *must* come *after* the above call to
    1502                 :   // mDocShell->SetChromeEventHandler() for the global window to get
    1503                 :   // the right chrome event handler.
    1504                 : 
    1505                 :   // Tell the window about the frame that hosts it.
    1506               0 :   nsCOMPtr<nsIDOMElement> frame_element(do_QueryInterface(mOwnerContent));
    1507               0 :   NS_ASSERTION(frame_element, "frame loader owner element not a DOM element!");
    1508                 : 
    1509               0 :   nsCOMPtr<nsPIDOMWindow> win_private(do_GetInterface(mDocShell));
    1510               0 :   nsCOMPtr<nsIBaseWindow> base_win(do_QueryInterface(mDocShell));
    1511               0 :   if (win_private) {
    1512               0 :     win_private->SetFrameElementInternal(frame_element);
    1513                 :   }
    1514                 : 
    1515                 :   // This is kinda whacky, this call doesn't really create anything,
    1516                 :   // but it must be called to make sure things are properly
    1517                 :   // initialized.
    1518               0 :   if (NS_FAILED(base_win->Create()) || !win_private) {
    1519                 :     // Do not call Destroy() here. See bug 472312.
    1520               0 :     NS_WARNING("Something wrong when creating the docshell for a frameloader!");
    1521               0 :     return NS_ERROR_FAILURE;
    1522                 :   }
    1523                 : 
    1524               0 :   EnsureMessageManager();
    1525                 : 
    1526               0 :   return NS_OK;
    1527                 : }
    1528                 : 
    1529                 : void
    1530               0 : nsFrameLoader::GetURL(nsString& aURI)
    1531                 : {
    1532               0 :   aURI.Truncate();
    1533                 : 
    1534               0 :   if (mOwnerContent->Tag() == nsGkAtoms::object) {
    1535               0 :     mOwnerContent->GetAttr(kNameSpaceID_None, nsGkAtoms::data, aURI);
    1536                 :   } else {
    1537               0 :     mOwnerContent->GetAttr(kNameSpaceID_None, nsGkAtoms::src, aURI);
    1538                 :   }
    1539               0 : }
    1540                 : 
    1541                 : nsresult
    1542               0 : nsFrameLoader::CheckForRecursiveLoad(nsIURI* aURI)
    1543                 : {
    1544                 :   nsresult rv;
    1545                 : 
    1546               0 :   mDepthTooGreat = false;
    1547               0 :   rv = MaybeCreateDocShell();
    1548               0 :   if (NS_FAILED(rv)) {
    1549               0 :     return rv;
    1550                 :   }
    1551               0 :   NS_ASSERTION(!mRemoteFrame,
    1552                 :                "Shouldn't call CheckForRecursiveLoad on remote frames.");
    1553               0 :   if (!mDocShell) {
    1554               0 :     return NS_ERROR_FAILURE;
    1555                 :   }
    1556                 : 
    1557               0 :   nsCOMPtr<nsIDocShellTreeItem> treeItem = do_QueryInterface(mDocShell);
    1558               0 :   NS_ASSERTION(treeItem, "docshell must be a treeitem!");
    1559                 : 
    1560                 :   // Check that we're still in the docshell tree.
    1561               0 :   nsCOMPtr<nsIDocShellTreeOwner> treeOwner;
    1562               0 :   treeItem->GetTreeOwner(getter_AddRefs(treeOwner));
    1563               0 :   NS_WARN_IF_FALSE(treeOwner,
    1564                 :                    "Trying to load a new url to a docshell without owner!");
    1565               0 :   NS_ENSURE_STATE(treeOwner);
    1566                 :   
    1567                 :   
    1568                 :   PRInt32 ourType;
    1569               0 :   rv = treeItem->GetItemType(&ourType);
    1570               0 :   if (NS_SUCCEEDED(rv) && ourType != nsIDocShellTreeItem::typeContent) {
    1571                 :     // No need to do recursion-protection here XXXbz why not??  Do we really
    1572                 :     // trust people not to screw up with non-content docshells?
    1573               0 :     return NS_OK;
    1574                 :   }
    1575                 : 
    1576                 :   // Bug 8065: Don't exceed some maximum depth in content frames
    1577                 :   // (MAX_DEPTH_CONTENT_FRAMES)
    1578               0 :   nsCOMPtr<nsIDocShellTreeItem> parentAsItem;
    1579               0 :   treeItem->GetSameTypeParent(getter_AddRefs(parentAsItem));
    1580               0 :   PRInt32 depth = 0;
    1581               0 :   while (parentAsItem) {
    1582               0 :     ++depth;
    1583                 :     
    1584               0 :     if (depth >= MAX_DEPTH_CONTENT_FRAMES) {
    1585               0 :       mDepthTooGreat = true;
    1586               0 :       NS_WARNING("Too many nested content frames so giving up");
    1587                 : 
    1588               0 :       return NS_ERROR_UNEXPECTED; // Too deep, give up!  (silently?)
    1589                 :     }
    1590                 : 
    1591               0 :     nsCOMPtr<nsIDocShellTreeItem> temp;
    1592               0 :     temp.swap(parentAsItem);
    1593               0 :     temp->GetSameTypeParent(getter_AddRefs(parentAsItem));
    1594                 :   }
    1595                 :   
    1596                 :   // Bug 136580: Check for recursive frame loading
    1597               0 :   PRInt32 matchCount = 0;
    1598               0 :   treeItem->GetSameTypeParent(getter_AddRefs(parentAsItem));
    1599               0 :   while (parentAsItem) {
    1600                 :     // Check the parent URI with the URI we're loading
    1601               0 :     nsCOMPtr<nsIWebNavigation> parentAsNav(do_QueryInterface(parentAsItem));
    1602               0 :     if (parentAsNav) {
    1603                 :       // Does the URI match the one we're about to load?
    1604               0 :       nsCOMPtr<nsIURI> parentURI;
    1605               0 :       parentAsNav->GetCurrentURI(getter_AddRefs(parentURI));
    1606               0 :       if (parentURI) {
    1607                 :         // Bug 98158/193011: We need to ignore data after the #
    1608                 :         bool equal;
    1609               0 :         rv = aURI->EqualsExceptRef(parentURI, &equal);
    1610               0 :         NS_ENSURE_SUCCESS(rv, rv);
    1611                 :         
    1612               0 :         if (equal) {
    1613               0 :           matchCount++;
    1614               0 :           if (matchCount >= MAX_SAME_URL_CONTENT_FRAMES) {
    1615               0 :             NS_WARNING("Too many nested content frames have the same url (recursion?) so giving up");
    1616               0 :             return NS_ERROR_UNEXPECTED;
    1617                 :           }
    1618                 :         }
    1619                 :       }
    1620                 :     }
    1621               0 :     nsCOMPtr<nsIDocShellTreeItem> temp;
    1622               0 :     temp.swap(parentAsItem);
    1623               0 :     temp->GetSameTypeParent(getter_AddRefs(parentAsItem));
    1624                 :   }
    1625                 : 
    1626               0 :   return NS_OK;
    1627                 : }
    1628                 : 
    1629                 : nsresult
    1630               0 : nsFrameLoader::GetWindowDimensions(nsRect& aRect)
    1631                 : {
    1632                 :   // Need to get outer window position here
    1633               0 :   nsIDocument* doc = mOwnerContent->GetDocument();
    1634               0 :   if (!doc) {
    1635               0 :     return NS_ERROR_FAILURE;
    1636                 :   }
    1637                 : 
    1638               0 :   if (doc->GetDisplayDocument()) {
    1639               0 :     return NS_ERROR_FAILURE;
    1640                 :   }
    1641                 : 
    1642                 :   nsCOMPtr<nsIWebNavigation> parentAsWebNav =
    1643               0 :     do_GetInterface(doc->GetScriptGlobalObject());
    1644                 : 
    1645               0 :   if (!parentAsWebNav) {
    1646               0 :     return NS_ERROR_FAILURE;
    1647                 :   }
    1648                 : 
    1649               0 :   nsCOMPtr<nsIDocShellTreeItem> parentAsItem(do_QueryInterface(parentAsWebNav));
    1650                 : 
    1651               0 :   nsCOMPtr<nsIDocShellTreeOwner> parentOwner;
    1652               0 :   if (NS_FAILED(parentAsItem->GetTreeOwner(getter_AddRefs(parentOwner))) ||
    1653               0 :       !parentOwner) {
    1654               0 :     return NS_ERROR_FAILURE;
    1655                 :   }
    1656                 : 
    1657               0 :   nsCOMPtr<nsIBaseWindow> treeOwnerAsWin(do_GetInterface(parentOwner));
    1658               0 :   treeOwnerAsWin->GetPosition(&aRect.x, &aRect.y);
    1659               0 :   treeOwnerAsWin->GetSize(&aRect.width, &aRect.height);
    1660               0 :   return NS_OK;
    1661                 : }
    1662                 : 
    1663                 : NS_IMETHODIMP
    1664               0 : nsFrameLoader::UpdatePositionAndSize(nsIFrame *aIFrame)
    1665                 : {
    1666               0 :   if (mRemoteFrame) {
    1667               0 :     if (mRemoteBrowser) {
    1668               0 :       nsIntSize size = GetSubDocumentSize(aIFrame);
    1669               0 :       nsRect dimensions;
    1670               0 :       NS_ENSURE_SUCCESS(GetWindowDimensions(dimensions), NS_ERROR_FAILURE);
    1671               0 :       mRemoteBrowser->UpdateDimensions(dimensions, size);
    1672                 :     }
    1673               0 :     return NS_OK;
    1674                 :   }
    1675               0 :   return UpdateBaseWindowPositionAndSize(aIFrame);
    1676                 : }
    1677                 : 
    1678                 : nsresult
    1679               0 : nsFrameLoader::UpdateBaseWindowPositionAndSize(nsIFrame *aIFrame)
    1680                 : {
    1681               0 :   nsCOMPtr<nsIDocShell> docShell;
    1682               0 :   GetDocShell(getter_AddRefs(docShell));
    1683               0 :   nsCOMPtr<nsIBaseWindow> baseWindow(do_QueryInterface(docShell));
    1684                 : 
    1685                 :   // resize the sub document
    1686               0 :   if (baseWindow) {
    1687               0 :     PRInt32 x = 0;
    1688               0 :     PRInt32 y = 0;
    1689                 : 
    1690               0 :     nsWeakFrame weakFrame(aIFrame);
    1691                 : 
    1692               0 :     baseWindow->GetPositionAndSize(&x, &y, nsnull, nsnull);
    1693                 : 
    1694               0 :     if (!weakFrame.IsAlive()) {
    1695                 :       // GetPositionAndSize() killed us
    1696               0 :       return NS_OK;
    1697                 :     }
    1698                 : 
    1699               0 :     nsIntSize size = GetSubDocumentSize(aIFrame);
    1700                 : 
    1701               0 :     baseWindow->SetPositionAndSize(x, y, size.width, size.height, false);
    1702                 :   }
    1703                 : 
    1704               0 :   return NS_OK;
    1705                 : }
    1706                 : 
    1707                 : NS_IMETHODIMP
    1708               0 : nsFrameLoader::GetRenderMode(PRUint32* aRenderMode)
    1709                 : {
    1710               0 :   *aRenderMode = mRenderMode;
    1711               0 :   return NS_OK;
    1712                 : }
    1713                 : 
    1714                 : NS_IMETHODIMP
    1715               0 : nsFrameLoader::SetRenderMode(PRUint32 aRenderMode)
    1716                 : {
    1717               0 :   if (aRenderMode == mRenderMode) {
    1718               0 :     return NS_OK;
    1719                 :   }
    1720                 : 
    1721               0 :   mRenderMode = aRenderMode;
    1722                 :   // NB: we pass INVALIDATE_NO_THEBES_LAYERS here to keep view
    1723                 :   // semantics the same for both in-process and out-of-process
    1724                 :   // <browser>.  This is just a transform of the layer subtree in
    1725                 :   // both.
    1726               0 :   InvalidateFrame(GetPrimaryFrameOfOwningContent(), nsIFrame::INVALIDATE_NO_THEBES_LAYERS);
    1727               0 :   return NS_OK;
    1728                 : }
    1729                 : 
    1730                 : NS_IMETHODIMP
    1731               0 : nsFrameLoader::GetEventMode(PRUint32* aEventMode)
    1732                 : {
    1733               0 :   *aEventMode = mEventMode;
    1734               0 :   return NS_OK;
    1735                 : }
    1736                 : 
    1737                 : NS_IMETHODIMP
    1738               0 : nsFrameLoader::SetEventMode(PRUint32 aEventMode)
    1739                 : {
    1740               0 :   mEventMode = aEventMode;
    1741               0 :   return NS_OK;
    1742                 : }
    1743                 : 
    1744                 : NS_IMETHODIMP
    1745               0 : nsFrameLoader::GetClipSubdocument(bool* aResult)
    1746                 : {
    1747               0 :   *aResult = mClipSubdocument;
    1748               0 :   return NS_OK;
    1749                 : }
    1750                 : 
    1751                 : NS_IMETHODIMP
    1752               0 : nsFrameLoader::SetClipSubdocument(bool aClip)
    1753                 : {
    1754               0 :   mClipSubdocument = aClip;
    1755               0 :   nsIFrame* frame = GetPrimaryFrameOfOwningContent();
    1756               0 :   if (frame) {
    1757               0 :     InvalidateFrame(frame, 0);
    1758               0 :     frame->PresContext()->PresShell()->
    1759               0 :       FrameNeedsReflow(frame, nsIPresShell::eResize, NS_FRAME_IS_DIRTY);
    1760               0 :     nsSubDocumentFrame* subdocFrame = do_QueryFrame(frame);
    1761               0 :     if (subdocFrame) {
    1762               0 :       nsIFrame* subdocRootFrame = subdocFrame->GetSubdocumentRootFrame();
    1763               0 :       if (subdocRootFrame) {
    1764                 :         nsIFrame* subdocRootScrollFrame = subdocRootFrame->PresContext()->PresShell()->
    1765               0 :           GetRootScrollFrame();
    1766               0 :         if (subdocRootScrollFrame) {
    1767               0 :           frame->PresContext()->PresShell()->
    1768               0 :             FrameNeedsReflow(frame, nsIPresShell::eResize, NS_FRAME_IS_DIRTY);
    1769                 :         }
    1770                 :       }
    1771                 :     }
    1772                 :   }
    1773               0 :   return NS_OK;
    1774                 : }
    1775                 : 
    1776                 : NS_IMETHODIMP
    1777               0 : nsFrameLoader::GetClampScrollPosition(bool* aResult)
    1778                 : {
    1779               0 :   *aResult = mClampScrollPosition;
    1780               0 :   return NS_OK;
    1781                 : }
    1782                 : 
    1783                 : NS_IMETHODIMP
    1784               0 : nsFrameLoader::SetClampScrollPosition(bool aClamp)
    1785                 : {
    1786               0 :   mClampScrollPosition = aClamp;
    1787                 : 
    1788                 :   // When turning clamping on, make sure the current position is clamped.
    1789               0 :   if (aClamp) {
    1790               0 :     nsIFrame* frame = GetPrimaryFrameOfOwningContent();
    1791               0 :     if (frame) {
    1792               0 :       nsSubDocumentFrame* subdocFrame = do_QueryFrame(frame);
    1793               0 :       if (subdocFrame) {
    1794               0 :         nsIFrame* subdocRootFrame = subdocFrame->GetSubdocumentRootFrame();
    1795               0 :         if (subdocRootFrame) {
    1796                 :           nsIScrollableFrame* subdocRootScrollFrame = subdocRootFrame->PresContext()->PresShell()->
    1797               0 :             GetRootScrollFrameAsScrollable();
    1798               0 :           if (subdocRootScrollFrame) {
    1799               0 :             subdocRootScrollFrame->ScrollTo(subdocRootScrollFrame->GetScrollPosition(), nsIScrollableFrame::INSTANT);
    1800                 :           }
    1801                 :         }
    1802                 :       }
    1803                 :     }
    1804                 :   }
    1805               0 :   return NS_OK;
    1806                 : }
    1807                 : 
    1808                 : nsIntSize
    1809               0 : nsFrameLoader::GetSubDocumentSize(const nsIFrame *aIFrame)
    1810                 : {
    1811               0 :   nsSize docSizeAppUnits;
    1812               0 :   nsPresContext* presContext = aIFrame->PresContext();
    1813                 :   nsCOMPtr<nsIDOMHTMLFrameElement> frameElem = 
    1814               0 :     do_QueryInterface(aIFrame->GetContent());
    1815               0 :   if (frameElem) {
    1816               0 :     docSizeAppUnits = aIFrame->GetSize();
    1817                 :   } else {
    1818               0 :     docSizeAppUnits = aIFrame->GetContentRect().Size();
    1819                 :   }
    1820                 :   return nsIntSize(presContext->AppUnitsToDevPixels(docSizeAppUnits.width),
    1821               0 :                    presContext->AppUnitsToDevPixels(docSizeAppUnits.height));
    1822                 : }
    1823                 : 
    1824                 : bool
    1825               0 : nsFrameLoader::TryRemoteBrowser()
    1826                 : {
    1827               0 :   NS_ASSERTION(!mRemoteBrowser, "TryRemoteBrowser called with a remote browser already?");
    1828                 : 
    1829               0 :   nsIDocument* doc = mOwnerContent->GetDocument();
    1830               0 :   if (!doc) {
    1831               0 :     return false;
    1832                 :   }
    1833                 : 
    1834               0 :   if (doc->GetDisplayDocument()) {
    1835                 :     // Don't allow subframe loads in external reference documents
    1836               0 :     return false;
    1837                 :   }
    1838                 : 
    1839                 :   nsCOMPtr<nsIWebNavigation> parentAsWebNav =
    1840               0 :     do_GetInterface(doc->GetScriptGlobalObject());
    1841                 : 
    1842               0 :   if (!parentAsWebNav) {
    1843               0 :     return false;
    1844                 :   }
    1845                 : 
    1846               0 :   nsCOMPtr<nsIDocShellTreeItem> parentAsItem(do_QueryInterface(parentAsWebNav));
    1847                 : 
    1848                 :   PRInt32 parentType;
    1849               0 :   parentAsItem->GetItemType(&parentType);
    1850                 : 
    1851               0 :   if (parentType != nsIDocShellTreeItem::typeChrome) {
    1852               0 :     return false;
    1853                 :   }
    1854                 : 
    1855               0 :   if (!mOwnerContent->IsXUL()) {
    1856               0 :     return false;
    1857                 :   }
    1858                 : 
    1859               0 :   nsAutoString value;
    1860               0 :   mOwnerContent->GetAttr(kNameSpaceID_None, nsGkAtoms::type, value);
    1861                 : 
    1862               0 :   if (!value.LowerCaseEqualsLiteral("content") &&
    1863               0 :       !StringBeginsWith(value, NS_LITERAL_STRING("content-"),
    1864               0 :                         nsCaseInsensitiveStringComparator())) {
    1865               0 :     return false;
    1866                 :   }
    1867                 : 
    1868               0 :   PRUint32 chromeFlags = 0;
    1869               0 :   nsCOMPtr<nsIDocShellTreeOwner> parentOwner;
    1870               0 :   if (NS_FAILED(parentAsItem->GetTreeOwner(getter_AddRefs(parentOwner))) ||
    1871               0 :       !parentOwner) {
    1872               0 :     return false;
    1873                 :   }
    1874               0 :   nsCOMPtr<nsIXULWindow> window(do_GetInterface(parentOwner));
    1875               0 :   if (!window) {
    1876               0 :     return false;
    1877                 :   }
    1878               0 :   if (NS_FAILED(window->GetChromeFlags(&chromeFlags))) {
    1879               0 :     return false;
    1880                 :   }
    1881                 : 
    1882               0 :   ContentParent* parent = ContentParent::GetNewOrUsed();
    1883               0 :   NS_ASSERTION(parent->IsAlive(), "Process parent should be alive; something is very wrong!");
    1884               0 :   mRemoteBrowser = parent->CreateTab(chromeFlags);
    1885               0 :   if (mRemoteBrowser) {
    1886               0 :     nsCOMPtr<nsIDOMElement> element = do_QueryInterface(mOwnerContent);
    1887               0 :     mRemoteBrowser->SetOwnerElement(element);
    1888                 : 
    1889               0 :     nsCOMPtr<nsIDocShellTreeItem> rootItem;
    1890               0 :     parentAsItem->GetRootTreeItem(getter_AddRefs(rootItem));
    1891               0 :     nsCOMPtr<nsIDOMWindow> rootWin = do_GetInterface(rootItem);
    1892               0 :     nsCOMPtr<nsIDOMChromeWindow> rootChromeWin = do_QueryInterface(rootWin);
    1893               0 :     NS_ABORT_IF_FALSE(rootChromeWin, "How did we not get a chrome window here?");
    1894                 : 
    1895               0 :     nsCOMPtr<nsIBrowserDOMWindow> browserDOMWin;
    1896               0 :     rootChromeWin->GetBrowserDOMWindow(getter_AddRefs(browserDOMWin));
    1897               0 :     mRemoteBrowser->SetBrowserDOMWindow(browserDOMWin);
    1898                 :     
    1899               0 :     mChildHost = parent;
    1900                 :   }
    1901               0 :   return true;
    1902                 : }
    1903                 : 
    1904                 : mozilla::dom::PBrowserParent*
    1905               0 : nsFrameLoader::GetRemoteBrowser()
    1906                 : {
    1907               0 :   return mRemoteBrowser;
    1908                 : }
    1909                 : 
    1910                 : NS_IMETHODIMP
    1911               0 : nsFrameLoader::ActivateRemoteFrame() {
    1912               0 :   if (mRemoteBrowser) {
    1913               0 :     mRemoteBrowser->Activate();
    1914               0 :     return NS_OK;
    1915                 :   }
    1916               0 :   return NS_ERROR_UNEXPECTED;
    1917                 : }
    1918                 : 
    1919                 : NS_IMETHODIMP
    1920               0 : nsFrameLoader::DeactivateRemoteFrame() {
    1921               0 :   if (mRemoteBrowser) {
    1922               0 :     mRemoteBrowser->Deactivate();
    1923               0 :     return NS_OK;
    1924                 :   }
    1925               0 :   return NS_ERROR_UNEXPECTED;
    1926                 : }
    1927                 : 
    1928                 : NS_IMETHODIMP
    1929               0 : nsFrameLoader::SendCrossProcessMouseEvent(const nsAString& aType,
    1930                 :                                           float aX,
    1931                 :                                           float aY,
    1932                 :                                           PRInt32 aButton,
    1933                 :                                           PRInt32 aClickCount,
    1934                 :                                           PRInt32 aModifiers,
    1935                 :                                           bool aIgnoreRootScrollFrame)
    1936                 : {
    1937               0 :   if (mRemoteBrowser) {
    1938                 :     mRemoteBrowser->SendMouseEvent(aType, aX, aY, aButton,
    1939                 :                                    aClickCount, aModifiers,
    1940               0 :                                    aIgnoreRootScrollFrame);
    1941               0 :     return NS_OK;
    1942                 :   }
    1943               0 :   return NS_ERROR_FAILURE;
    1944                 : }
    1945                 : 
    1946                 : NS_IMETHODIMP
    1947               0 : nsFrameLoader::ActivateFrameEvent(const nsAString& aType,
    1948                 :                                   bool aCapture)
    1949                 : {
    1950               0 :   if (mRemoteBrowser) {
    1951               0 :     return mRemoteBrowser->SendActivateFrameEvent(nsString(aType), aCapture) ?
    1952               0 :       NS_OK : NS_ERROR_NOT_AVAILABLE;
    1953                 :   }
    1954               0 :   return NS_ERROR_FAILURE;
    1955                 : }
    1956                 : 
    1957                 : NS_IMETHODIMP
    1958               0 : nsFrameLoader::SendCrossProcessKeyEvent(const nsAString& aType,
    1959                 :                                         PRInt32 aKeyCode,
    1960                 :                                         PRInt32 aCharCode,
    1961                 :                                         PRInt32 aModifiers,
    1962                 :                                         bool aPreventDefault)
    1963                 : {
    1964               0 :   if (mRemoteBrowser) {
    1965                 :     mRemoteBrowser->SendKeyEvent(aType, aKeyCode, aCharCode, aModifiers,
    1966               0 :                                  aPreventDefault);
    1967               0 :     return NS_OK;
    1968                 :   }
    1969               0 :   return NS_ERROR_FAILURE;
    1970                 : }
    1971                 : 
    1972                 : NS_IMETHODIMP
    1973               0 : nsFrameLoader::GetDelayRemoteDialogs(bool* aRetVal)
    1974                 : {
    1975               0 :   *aRetVal = mDelayRemoteDialogs;
    1976               0 :   return NS_OK;
    1977                 : }
    1978                 : 
    1979                 : NS_IMETHODIMP
    1980               0 : nsFrameLoader::SetDelayRemoteDialogs(bool aDelay)
    1981                 : {
    1982               0 :   if (mRemoteBrowser && mDelayRemoteDialogs && !aDelay) {
    1983                 :     nsRefPtr<nsIRunnable> ev =
    1984                 :       NS_NewRunnableMethod(mRemoteBrowser,
    1985               0 :                            &mozilla::dom::TabParent::HandleDelayedDialogs);
    1986               0 :     NS_DispatchToCurrentThread(ev);
    1987                 :   }
    1988               0 :   mDelayRemoteDialogs = aDelay;
    1989               0 :   return NS_OK;
    1990                 : }
    1991                 : 
    1992                 : nsresult
    1993               0 : nsFrameLoader::CreateStaticClone(nsIFrameLoader* aDest)
    1994                 : {
    1995               0 :   nsFrameLoader* dest = static_cast<nsFrameLoader*>(aDest);
    1996               0 :   dest->MaybeCreateDocShell();
    1997               0 :   NS_ENSURE_STATE(dest->mDocShell);
    1998                 : 
    1999               0 :   nsCOMPtr<nsIDOMDocument> dummy = do_GetInterface(dest->mDocShell);
    2000               0 :   nsCOMPtr<nsIContentViewer> viewer;
    2001               0 :   dest->mDocShell->GetContentViewer(getter_AddRefs(viewer));
    2002               0 :   NS_ENSURE_STATE(viewer);
    2003                 : 
    2004               0 :   nsCOMPtr<nsIDocShell> origDocShell;
    2005               0 :   GetDocShell(getter_AddRefs(origDocShell));
    2006               0 :   nsCOMPtr<nsIDOMDocument> domDoc = do_GetInterface(origDocShell);
    2007                 : 
    2008               0 :   nsCOMPtr<nsIDocument> doc = do_QueryInterface(domDoc);
    2009               0 :   NS_ENSURE_STATE(doc);
    2010               0 :   nsCOMPtr<nsIDocument> clonedDoc = doc->CreateStaticClone(dest->mDocShell);
    2011               0 :   nsCOMPtr<nsIDOMDocument> clonedDOMDoc = do_QueryInterface(clonedDoc);
    2012                 : 
    2013               0 :   viewer->SetDOMDocument(clonedDOMDoc);
    2014               0 :   return NS_OK;
    2015                 : }
    2016                 : 
    2017               0 : bool LoadScript(void* aCallbackData, const nsAString& aURL)
    2018                 : {
    2019                 :   mozilla::dom::PBrowserParent* tabParent =
    2020               0 :     static_cast<nsFrameLoader*>(aCallbackData)->GetRemoteBrowser();
    2021               0 :   if (tabParent) {
    2022               0 :     return tabParent->SendLoadRemoteScript(nsString(aURL));
    2023                 :   }
    2024               0 :   nsFrameLoader* fl = static_cast<nsFrameLoader*>(aCallbackData);
    2025                 :   nsRefPtr<nsInProcessTabChildGlobal> tabChild =
    2026               0 :     static_cast<nsInProcessTabChildGlobal*>(fl->GetTabChildGlobalAsEventTarget());
    2027               0 :   if (tabChild) {
    2028               0 :     tabChild->LoadFrameScript(aURL);
    2029                 :   }
    2030               0 :   return true;
    2031                 : }
    2032                 : 
    2033                 : class nsAsyncMessageToChild : public nsRunnable
    2034               0 : {
    2035                 : public:
    2036               0 :   nsAsyncMessageToChild(nsFrameLoader* aFrameLoader,
    2037                 :                         const nsAString& aMessage, const nsAString& aJSON)
    2038               0 :     : mFrameLoader(aFrameLoader), mMessage(aMessage), mJSON(aJSON) {}
    2039                 : 
    2040               0 :   NS_IMETHOD Run()
    2041                 :   {
    2042                 :     nsInProcessTabChildGlobal* tabChild =
    2043               0 :       static_cast<nsInProcessTabChildGlobal*>(mFrameLoader->mChildMessageManager.get());
    2044               0 :     if (tabChild && tabChild->GetInnerManager()) {
    2045               0 :       nsFrameScriptCx cx(static_cast<nsIDOMEventTarget*>(tabChild), tabChild);
    2046               0 :       nsRefPtr<nsFrameMessageManager> mm = tabChild->GetInnerManager();
    2047                 :       mm->ReceiveMessage(static_cast<nsIDOMEventTarget*>(tabChild), mMessage,
    2048               0 :                          false, mJSON, nsnull, nsnull);
    2049                 :     }
    2050               0 :     return NS_OK;
    2051                 :   }
    2052                 :   nsRefPtr<nsFrameLoader> mFrameLoader;
    2053                 :   nsString mMessage;
    2054                 :   nsString mJSON;
    2055                 : };
    2056                 : 
    2057               0 : bool SendAsyncMessageToChild(void* aCallbackData,
    2058                 :                              const nsAString& aMessage,
    2059                 :                              const nsAString& aJSON)
    2060                 : {
    2061                 :   mozilla::dom::PBrowserParent* tabParent =
    2062               0 :     static_cast<nsFrameLoader*>(aCallbackData)->GetRemoteBrowser();
    2063               0 :   if (tabParent) {
    2064               0 :     return tabParent->SendAsyncMessage(nsString(aMessage), nsString(aJSON));
    2065                 :   }
    2066                 :   nsRefPtr<nsIRunnable> ev =
    2067                 :     new nsAsyncMessageToChild(static_cast<nsFrameLoader*>(aCallbackData),
    2068               0 :                               aMessage, aJSON);
    2069               0 :   NS_DispatchToCurrentThread(ev);
    2070               0 :   return true;
    2071                 : }
    2072                 : 
    2073                 : NS_IMETHODIMP
    2074               0 : nsFrameLoader::GetMessageManager(nsIChromeFrameMessageManager** aManager)
    2075                 : {
    2076               0 :   EnsureMessageManager();
    2077               0 :   if (mMessageManager) {
    2078               0 :     CallQueryInterface(mMessageManager, aManager);
    2079                 :   }
    2080               0 :   return NS_OK;
    2081                 : }
    2082                 : 
    2083                 : NS_IMETHODIMP
    2084               0 : nsFrameLoader::GetContentViewsIn(float aXPx, float aYPx,
    2085                 :                                  float aTopSize, float aRightSize,
    2086                 :                                  float aBottomSize, float aLeftSize,
    2087                 :                                  PRUint32* aLength,
    2088                 :                                  nsIContentView*** aResult)
    2089                 : {
    2090               0 :   nscoord x = nsPresContext::CSSPixelsToAppUnits(aXPx - aLeftSize);
    2091               0 :   nscoord y = nsPresContext::CSSPixelsToAppUnits(aYPx - aTopSize);
    2092               0 :   nscoord w = nsPresContext::CSSPixelsToAppUnits(aLeftSize + aRightSize) + 1;
    2093               0 :   nscoord h = nsPresContext::CSSPixelsToAppUnits(aTopSize + aBottomSize) + 1;
    2094               0 :   nsRect target(x, y, w, h);
    2095                 : 
    2096               0 :   nsIFrame* frame = GetPrimaryFrameOfOwningContent();
    2097                 : 
    2098               0 :   nsTArray<ViewID> ids;
    2099               0 :   nsLayoutUtils::GetRemoteContentIds(frame, target, ids, true);
    2100               0 :   if (ids.Length() == 0 || !GetCurrentRemoteFrame()) {
    2101               0 :     *aResult = nsnull;
    2102               0 :     *aLength = 0;
    2103               0 :     return NS_OK;
    2104                 :   }
    2105                 : 
    2106                 :   nsIContentView** result = reinterpret_cast<nsIContentView**>(
    2107               0 :     NS_Alloc(ids.Length() * sizeof(nsIContentView*)));
    2108                 : 
    2109               0 :   for (PRUint32 i = 0; i < ids.Length(); i++) {
    2110               0 :     nsIContentView* view = GetCurrentRemoteFrame()->GetContentView(ids[i]);
    2111               0 :     NS_ABORT_IF_FALSE(view, "Retrieved ID from RenderFrameParent, it should be valid!");
    2112               0 :     nsRefPtr<nsIContentView>(view).forget(&result[i]);
    2113                 :   }
    2114                 : 
    2115               0 :   *aResult = result;
    2116               0 :   *aLength = ids.Length();
    2117                 : 
    2118               0 :   return NS_OK;
    2119                 : }
    2120                 : 
    2121                 : NS_IMETHODIMP
    2122               0 : nsFrameLoader::GetRootContentView(nsIContentView** aContentView)
    2123                 : {
    2124               0 :   RenderFrameParent* rfp = GetCurrentRemoteFrame();
    2125               0 :   if (!rfp) {
    2126               0 :     *aContentView = nsnull;
    2127               0 :     return NS_OK;
    2128                 :   }
    2129                 : 
    2130               0 :   nsContentView* view = rfp->GetContentView();
    2131               0 :   NS_ABORT_IF_FALSE(view, "Should always be able to create root scrollable!");
    2132               0 :   nsRefPtr<nsIContentView>(view).forget(aContentView);
    2133                 : 
    2134               0 :   return NS_OK;
    2135                 : }
    2136                 : 
    2137                 : nsresult
    2138               0 : nsFrameLoader::EnsureMessageManager()
    2139                 : {
    2140               0 :   NS_ENSURE_STATE(mOwnerContent);
    2141                 : 
    2142               0 :   nsresult rv = MaybeCreateDocShell();
    2143               0 :   if (NS_FAILED(rv)) {
    2144               0 :     return rv;
    2145                 :   }
    2146                 : 
    2147               0 :   if (!mIsTopLevelContent && !mRemoteFrame) {
    2148               0 :     return NS_OK;
    2149                 :   }
    2150                 : 
    2151               0 :   if (mMessageManager) {
    2152               0 :     if (ShouldUseRemoteProcess()) {
    2153               0 :       mMessageManager->SetCallbackData(mRemoteBrowserShown ? this : nsnull);
    2154                 :     }
    2155               0 :     return NS_OK;
    2156                 :   }
    2157                 : 
    2158               0 :   nsIScriptContext* sctx = mOwnerContent->GetContextForEventHandlers(&rv);
    2159               0 :   NS_ENSURE_SUCCESS(rv, rv);
    2160               0 :   NS_ENSURE_STATE(sctx);
    2161               0 :   JSContext* cx = sctx->GetNativeContext();
    2162               0 :   NS_ENSURE_STATE(cx);
    2163                 : 
    2164                 :   nsCOMPtr<nsIDOMChromeWindow> chromeWindow =
    2165               0 :     do_QueryInterface(mOwnerContent->OwnerDoc()->GetWindow());
    2166               0 :   NS_ENSURE_STATE(chromeWindow);
    2167               0 :   nsCOMPtr<nsIChromeFrameMessageManager> parentManager;
    2168               0 :   chromeWindow->GetMessageManager(getter_AddRefs(parentManager));
    2169                 : 
    2170               0 :   if (ShouldUseRemoteProcess()) {
    2171                 :     mMessageManager = new nsFrameMessageManager(true,
    2172                 :                                                 nsnull,
    2173                 :                                                 SendAsyncMessageToChild,
    2174                 :                                                 LoadScript,
    2175                 :                                                 mRemoteBrowserShown ? this : nsnull,
    2176               0 :                                                 static_cast<nsFrameMessageManager*>(parentManager.get()),
    2177               0 :                                                 cx);
    2178               0 :     NS_ENSURE_TRUE(mMessageManager, NS_ERROR_OUT_OF_MEMORY);
    2179                 :   } else
    2180                 :   {
    2181                 : 
    2182                 :     mMessageManager = new nsFrameMessageManager(true,
    2183                 :                                                 nsnull,
    2184                 :                                                 SendAsyncMessageToChild,
    2185                 :                                                 LoadScript,
    2186                 :                                                 nsnull,
    2187               0 :                                                 static_cast<nsFrameMessageManager*>(parentManager.get()),
    2188               0 :                                                 cx);
    2189               0 :     NS_ENSURE_TRUE(mMessageManager, NS_ERROR_OUT_OF_MEMORY);
    2190                 :     mChildMessageManager =
    2191               0 :       new nsInProcessTabChildGlobal(mDocShell, mOwnerContent, mMessageManager);
    2192               0 :     mMessageManager->SetCallbackData(this);
    2193                 :   }
    2194               0 :   return NS_OK;
    2195                 : }
    2196                 : 
    2197                 : nsIDOMEventTarget*
    2198               0 : nsFrameLoader::GetTabChildGlobalAsEventTarget()
    2199                 : {
    2200               0 :   return static_cast<nsInProcessTabChildGlobal*>(mChildMessageManager.get());
    2201            4392 : }

Generated by: LCOV version 1.7