Bug 433616 part 1. Make it possible to create a document viewer with no parent widget or container, and make various code saner about handling null document/prescontext/documentviewer containers. r=roc, sr=jst
authorBoris Zbarsky <bzbarsky@mit.edu>
Sun, 28 Sep 2008 15:14:28 -0400
changeset 19869 fc3d4c4384c2464aafdde0e2b346bdb4369a5128
parent 19868 aa4d3083995f851d9a075eec55baed0c94c95984
child 19870 a95a069f3372e5b404f21cd7501828d575556acb
push id2507
push userbzbarsky@mozilla.com
push dateMon, 29 Sep 2008 18:40:12 +0000
treeherdermozilla-central@a95a069f3372 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersroc, jst
bugs433616
milestone1.9.1b1pre
Bug 433616 part 1. Make it possible to create a document viewer with no parent widget or container, and make various code saner about handling null document/prescontext/documentviewer containers. r=roc, sr=jst
content/base/public/nsContentUtils.h
content/base/src/nsContentUtils.cpp
content/base/src/nsDocument.cpp
content/events/src/nsEventStateManager.cpp
content/html/document/src/nsHTMLDocument.cpp
dom/src/base/nsFocusController.cpp
layout/base/nsDocumentViewer.cpp
layout/base/nsPresShell.cpp
layout/forms/nsFileControlFrame.cpp
layout/style/nsMediaFeatures.cpp
layout/xul/base/src/nsTitleBarFrame.cpp
--- a/content/base/public/nsContentUtils.h
+++ b/content/base/public/nsContentUtils.h
@@ -803,16 +803,23 @@ public:
                                         nsXPIDLString& aResult);
 
   /**
    * Returns true if aDocument is a chrome document
    */
   static PRBool IsChromeDoc(nsIDocument *aDocument);
 
   /**
+   * Returns true if aDocument belongs to a chrome docshell for
+   * display purposes.  Returns false for null documents or documents
+   * which do not belong to a docshell.
+   */
+  static PRBool IsInChromeDocshell(nsIDocument *aDocument);
+
+  /**
    * Release *aSupportsPtr when the shutdown notification is received
    */
   static nsresult ReleasePtrOnShutdown(nsISupports** aSupportsPtr) {
     NS_ASSERTION(aSupportsPtr, "Expect to crash!");
     NS_ASSERTION(*aSupportsPtr, "Expect to crash!");
     return sPtrsToPtrsToRelease->AppendElement(aSupportsPtr) ? NS_OK :
       NS_ERROR_OUT_OF_MEMORY;
   }
--- a/content/base/src/nsContentUtils.cpp
+++ b/content/base/src/nsContentUtils.cpp
@@ -2899,16 +2899,34 @@ nsContentUtils::IsChromeDoc(nsIDocument 
   
   nsCOMPtr<nsIPrincipal> systemPrincipal;
   sSecurityManager->GetSystemPrincipal(getter_AddRefs(systemPrincipal));
 
   return aDocument->NodePrincipal() == systemPrincipal;
 }
 
 // static
+PRBool
+nsContentUtils::IsInChromeDocshell(nsIDocument *aDocument)
+{
+  if (!aDocument) {
+    return PR_FALSE;
+  }
+
+  nsCOMPtr<nsISupports> docContainer = aDocument->GetContainer();
+  nsCOMPtr<nsIDocShellTreeItem> docShell(do_QueryInterface(docContainer));
+  PRInt32 itemType = nsIDocShellTreeItem::typeContent;
+  if (docShell) {
+    docShell->GetItemType(&itemType);
+  }
+
+  return itemType == nsIDocShellTreeItem::typeChrome;
+}
+
+// static
 nsIContentPolicy*
 nsContentUtils::GetContentPolicy()
 {
   if (!sTriedToGetContentPolicy) {
     CallGetService(NS_CONTENTPOLICY_CONTRACTID, &sContentPolicyService);
     // It's OK to not have a content policy service
     sTriedToGetContentPolicy = PR_TRUE;
   }
--- a/content/base/src/nsDocument.cpp
+++ b/content/base/src/nsDocument.cpp
@@ -5722,19 +5722,17 @@ nsDocument::FlushPendingNotifications(mo
   // Determine if it is safe to flush the sink notifications
   // by determining if it safe to flush all the presshells.
   if (sink && (aType == Flush_Content || IsSafeToFlush())) {
     sink->FlushPendingNotifications(aType);
   }
 
   // Should we be flushing pending binding constructors in here?
 
-  nsPIDOMWindow *window = GetWindow();
-
-  if (aType <= Flush_ContentAndNotify || !window) {
+  if (aType <= Flush_ContentAndNotify) {
     // Nothing to do here
     return;
   }
 
   // If we have a parent we must flush the parent too to ensure that our
   // container is reflown if its size was changed.  But if it's not safe to
   // flush ourselves, then don't flush the parent, since that can cause things
   // like resizes of our frame's widget, which we can't handle while flushing
--- a/content/events/src/nsEventStateManager.cpp
+++ b/content/events/src/nsEventStateManager.cpp
@@ -6277,16 +6277,19 @@ nsEventStateManager::ShiftFocusByDoc(PRB
   // ShiftFocus.  The docshell tree should be kept in depth-first frame tree
   // order, the same as we use for tabbing, so the effect should be the same,
   // but this is much faster.
 
   NS_ASSERTION(mPresContext, "no prescontext");
 
   nsCOMPtr<nsISupports> pcContainer = mPresContext->GetContainer();
   nsCOMPtr<nsIDocShellTreeNode> curNode = do_QueryInterface(pcContainer);
+  if (!curNode) {
+    return;
+  }
 
   // perform a depth first search (preorder) of the docshell tree
   // looking for an HTML Frame or a chrome document
 
   nsCOMPtr<nsIDocShellTreeItem> nextItem;
   nsCOMPtr<nsIDocShell> nextShell;
   do {
     if (aForward) {
--- a/content/html/document/src/nsHTMLDocument.cpp
+++ b/content/html/document/src/nsHTMLDocument.cpp
@@ -704,34 +704,36 @@ nsHTMLDocument::StartDocumentLoad(const 
       cacheDescriptor = do_QueryInterface(cacheToken);
   }
 
   if (needsParser) {
     mParser = do_CreateInstance(kCParserCID, &rv);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
-  nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(aContainer));
-
-  nsCOMPtr<nsIDocumentCharsetInfo> dcInfo;
-  docShell->GetDocumentCharsetInfo(getter_AddRefs(dcInfo));
   PRInt32 textType = GET_BIDI_OPTION_TEXTTYPE(GetBidiOptions());
 
   // Look for the parent document.  Note that at this point we don't have our
   // content viewer set up yet, and therefore do not have a useful
   // mParentDocument.
 
   // in this block of code, if we get an error result, we return it
   // but if we get a null pointer, that's perfectly legal for parent
   // and parentContentViewer
+  nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(aContainer));
+
+  // No support yet for docshell-less HTML
+  NS_ENSURE_TRUE(docShell || IsXHTML(), NS_ERROR_FAILURE);
+
   nsCOMPtr<nsIDocShellTreeItem> docShellAsItem(do_QueryInterface(docShell));
-  NS_ENSURE_TRUE(docShellAsItem, NS_ERROR_FAILURE);
 
   nsCOMPtr<nsIDocShellTreeItem> parentAsItem;
-  docShellAsItem->GetSameTypeParent(getter_AddRefs(parentAsItem));
+  if (docShellAsItem) {
+    docShellAsItem->GetSameTypeParent(getter_AddRefs(parentAsItem));
+  }
 
   nsCOMPtr<nsIDocShell> parent(do_QueryInterface(parentAsItem));
   nsCOMPtr<nsIDocument> parentDocument;
   nsCOMPtr<nsIContentViewer> parentContentViewer;
   if (parent) {
     rv = parent->GetContentViewer(getter_AddRefs(parentContentViewer));
     NS_ENSURE_SUCCESS(rv, rv);
     nsCOMPtr<nsIDocumentViewer> docViewer =
@@ -742,17 +744,19 @@ nsHTMLDocument::StartDocumentLoad(const 
   }
 
   //
   // The following logic is mirrored in nsWebShell::Embed!
   //
   nsCOMPtr<nsIMarkupDocumentViewer> muCV;
   PRBool muCVIsParent = PR_FALSE;
   nsCOMPtr<nsIContentViewer> cv;
-  docShell->GetContentViewer(getter_AddRefs(cv));
+  if (docShell) {
+    docShell->GetContentViewer(getter_AddRefs(cv));
+  }
   if (cv) {
      muCV = do_QueryInterface(cv);
   } else {
     muCV = do_QueryInterface(parentContentViewer);
     if (muCV) {
       muCVIsParent = PR_TRUE;
     }
   }
@@ -779,16 +783,21 @@ nsHTMLDocument::StartDocumentLoad(const 
   
   if (IsXHTML()) {
     charsetSource = kCharsetFromDocTypeDefault;
     charset.AssignLiteral("UTF-8");
     TryChannelCharset(aChannel, charsetSource, charset);
     parserCharsetSource = charsetSource;
     parserCharset = charset;
   } else {
+    NS_ASSERTION(docShell && docShellAsItem, "Unexpected null value");
+    
+    nsCOMPtr<nsIDocumentCharsetInfo> dcInfo;
+    docShell->GetDocumentCharsetInfo(getter_AddRefs(dcInfo));
+
     charsetSource = kCharsetUninitialized;
     wyciwygChannel = do_QueryInterface(aChannel);
 
     // The following charset resolving calls has implied knowledge
     // about charset source priority order. Each try will return true
     // if the source is higher or equal to the source as its name
     // describes. Some try call might change charset source to
     // multiple values, like TryHintCharset and TryParentCharset. It
--- a/dom/src/base/nsFocusController.cpp
+++ b/dom/src/base/nsFocusController.cpp
@@ -418,17 +418,17 @@ nsFocusController::Blur(nsIDOMEvent* aEv
   return NS_OK;
 }
 
 nsPIDOMWindow *
 nsFocusController::GetWindowFromDocument(nsIDOMDocument* aDocument)
 {
   nsCOMPtr<nsIDocument> doc = do_QueryInterface(aDocument);
   if (!doc)
-    return NS_OK;
+    return nsnull;
 
   return doc->GetWindow();
 }
 
 NS_IMETHODIMP
 nsFocusController::GetControllerForCommand(const char * aCommand,
                                            nsIController** _retval)
 {
--- a/layout/base/nsDocumentViewer.cpp
+++ b/layout/base/nsDocumentViewer.cpp
@@ -428,17 +428,17 @@ protected:
   nsCOMPtr<nsIStyleSheet>  mUAStyleSheet;
 
   nsCOMPtr<nsISelectionListener> mSelectionListener;
   nsCOMPtr<nsIDOMFocusListener> mFocusListener;
 
   nsCOMPtr<nsIContentViewer> mPreviousViewer;
   nsCOMPtr<nsISHEntry> mSHEntry;
 
-  nsIWidget* mParentWidget;          // purposely won't be ref counted
+  nsIWidget* mParentWidget; // purposely won't be ref counted.  May be null
 
   // mTextZoom/mPageZoom record the textzoom/pagezoom of the first (galley)
   // presshell only.
   float mTextZoom;      // Text zoom, defaults to 1.0
   float mPageZoom;
 
   PRInt16 mNumURLStarts;
   PRInt16 mDestroyRefCount;    // a second "refcount" for the document viewer's "destroy"
@@ -953,24 +953,21 @@ DocumentViewerImpl::LoadComplete(nsresul
   }
   
   nsresult rv = NS_OK;
   NS_ENSURE_TRUE(mDocument, NS_ERROR_NOT_AVAILABLE);
 
   // First, get the window from the document...
   nsPIDOMWindow *window = mDocument->GetWindow();
 
-  // Fail if no window is available...
-  NS_ENSURE_TRUE(window, NS_ERROR_NULL_POINTER);
-
   mLoaded = PR_TRUE;
 
   // Now, fire either an OnLoad or OnError event to the document...
   PRBool restoring = PR_FALSE;
-  if(NS_SUCCEEDED(aStatus)) {
+  if(NS_SUCCEEDED(aStatus) && window) {
     nsEventStatus status = nsEventStatus_eIgnore;
     nsEvent event(PR_TRUE, NS_LOAD);
     event.flags |= NS_EVENT_FLAG_CANT_BUBBLE;
      // XXX Dispatching to |window|, but using |document| as the target.
     event.target = mDocument;
 
     // If the document presentation is being restored, we don't want to fire
     // onload to the document content since that would likely confuse scripts
@@ -1236,42 +1233,38 @@ AttachContainerRecurse(nsIDocShell* aShe
   }
 }
 
 NS_IMETHODIMP
 DocumentViewerImpl::Open(nsISupports *aState, nsISHEntry *aSHEntry)
 {
   NS_ENSURE_TRUE(mPresShell, NS_ERROR_NOT_INITIALIZED);
 
-  // Our container might have gone away while we were closed.
-  // If this is the case, we must fail to open so we don't crash.
-  nsCOMPtr<nsISupports> container = do_QueryReferent(mContainer);
-  if (!container)
-    return NS_ERROR_NOT_AVAILABLE;
-
   nsRect bounds;
   mWindow->GetBounds(bounds);
 
   nsresult rv = InitInternal(mParentWidget, aState, bounds, PR_FALSE, PR_FALSE);
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (mDocument)
     mDocument->SetContainer(nsCOMPtr<nsISupports>(do_QueryReferent(mContainer)));
 
   if (mPresShell)
     mPresShell->SetForwardingContainer(nsnull);
 
   // Rehook the child presentations.  The child shells are still in
   // session history, so get them from there.
 
-  nsCOMPtr<nsIDocShellTreeItem> item;
-  PRInt32 itemIndex = 0;
-  while (NS_SUCCEEDED(aSHEntry->ChildShellAt(itemIndex++,
-                                             getter_AddRefs(item))) && item) {
-    AttachContainerRecurse(nsCOMPtr<nsIDocShell>(do_QueryInterface(item)));
+  if (aSHEntry) {
+    nsCOMPtr<nsIDocShellTreeItem> item;
+    PRInt32 itemIndex = 0;
+    while (NS_SUCCEEDED(aSHEntry->ChildShellAt(itemIndex++,
+                                               getter_AddRefs(item))) && item) {
+      AttachContainerRecurse(nsCOMPtr<nsIDocShell>(do_QueryInterface(item)));
+    }
   }
   
   SyncParentSubDocMap();
 
   if (mFocusListener && mDocument) {
     mDocument->AddEventListenerByIID(mFocusListener,
                                      NS_GET_IID(nsIDOMFocusListener));
   }
@@ -1868,38 +1861,43 @@ DocumentViewerImpl::Show(void)
   }
 
   if (mWindow) {
     mWindow->Show(PR_TRUE);
   }
 
   if (mDocument && !mPresShell && !mWindow) {
     nsCOMPtr<nsIBaseWindow> base_win(do_QueryReferent(mContainer));
-    NS_ENSURE_TRUE(base_win, NS_ERROR_UNEXPECTED);
-
-    base_win->GetParentWidget(&mParentWidget);
-    NS_ENSURE_TRUE(mParentWidget, NS_ERROR_UNEXPECTED);
-    mParentWidget->Release(); // GetParentWidget AddRefs, but mParentWidget is weak
+    if (base_win) {
+      base_win->GetParentWidget(&mParentWidget);
+      NS_ENSURE_TRUE(mParentWidget, NS_ERROR_UNEXPECTED);
+      mParentWidget->Release(); // GetParentWidget AddRefs, but mParentWidget is weak
+    }
 
     nsresult rv = CreateDeviceContext(mParentWidget);
     NS_ENSURE_SUCCESS(rv, rv);
 
     // Create presentation context
     NS_ASSERTION(!mPresContext, "Shouldn't have a prescontext if we have no shell!");
     mPresContext = new nsPresContext(mDocument, nsPresContext::eContext_Galley);
     NS_ENSURE_TRUE(mPresContext, NS_ERROR_OUT_OF_MEMORY);
 
     rv = mPresContext->Init(mDeviceContext);
     if (NS_FAILED(rv)) {
       mPresContext = nsnull;
       return rv;
     }
 
     nsRect tbounds;
-    mParentWidget->GetBounds(tbounds);
+    if (mParentWidget) {
+      mParentWidget->GetBounds(tbounds);
+    } else {
+      // No good default size; just size to 0 by 0 for lack of anything better.
+      tbounds = nsRect(0, 0, 0, 0);
+    }
 
     rv = MakeWindow(nsSize(mPresContext->DevPixelsToAppUnits(tbounds.width),
                            mPresContext->DevPixelsToAppUnits(tbounds.height)));
     if (NS_FAILED(rv))
       return rv;
 
     if (mPresContext && base_win) {
       nsCOMPtr<nsILinkHandler> linkHandler(do_GetInterface(base_win));
@@ -2093,19 +2091,21 @@ DocumentViewerImpl::CreateStyleSet(nsIDo
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
   styleSet->BeginUpdate();
   
   // The document will fill in the document sheets when we create the presshell
   
   // Handle the user sheets.
+  PRInt32 shellType = nsIDocShellTreeItem::typeContent;;
   nsCOMPtr<nsIDocShellTreeItem> docShell(do_QueryReferent(mContainer));
-  PRInt32 shellType;
-  docShell->GetItemType(&shellType);
+  if (docShell) {
+    docShell->GetItemType(&shellType);
+  }
   nsICSSStyleSheet* sheet = nsnull;
   if (shellType == nsIDocShellTreeItem::typeChrome) {
     sheet = nsLayoutStylesheetCache::UserChromeSheet();
   }
   else {
     sheet = nsLayoutStylesheetCache::UserContentSheet();
   }
 
@@ -2114,17 +2114,19 @@ DocumentViewerImpl::CreateStyleSet(nsIDo
 
   // Append chrome sheets (scrollbars + forms).
   PRBool shouldOverride = PR_FALSE;
   nsCOMPtr<nsIDocShell> ds(do_QueryInterface(docShell));
   nsCOMPtr<nsIDOMEventTarget> chromeHandler;
   nsCOMPtr<nsIURI> uri;
   nsCOMPtr<nsICSSStyleSheet> csssheet;
 
-  ds->GetChromeEventHandler(getter_AddRefs(chromeHandler));
+  if (ds) {
+    ds->GetChromeEventHandler(getter_AddRefs(chromeHandler));
+  }
   if (chromeHandler) {
     nsCOMPtr<nsIDOMElement> elt(do_QueryInterface(chromeHandler));
     nsCOMPtr<nsIContent> content(do_QueryInterface(elt));
     if (elt && content) {
       nsCOMPtr<nsIURI> baseURI = content->GetBaseURI();
 
       nsAutoString sheets;
       elt->GetAttribute(NS_LITERAL_STRING("usechromesheets"), sheets);
@@ -2204,17 +2206,18 @@ DocumentViewerImpl::MakeWindow(const nsS
   nsIDeviceContext *dx = mPresContext->DeviceContext();
 
   rv = mViewManager->Init(dx);
   if (NS_FAILED(rv))
     return rv;
 
   // Create a child window of the parent that is our "root view/window"
   // if aParentWidget has a view, we'll hook our view manager up to its view tree
-  nsIView* containerView = nsIView::GetViewFor(mParentWidget);
+  nsIView* containerView =
+    mParentWidget ? nsIView::GetViewFor(mParentWidget) : nsnull;
 
   if (containerView) {
     // see if the containerView has already been hooked into a foreign view manager hierarchy
     // if it has, then we have to hook into the hierarchy too otherwise bad things will happen.
     nsIViewManager* containerVM = containerView->GetViewManager();
     nsIView* pView = containerView;
     do {
       pView = pView->GetParent();
@@ -2246,18 +2249,31 @@ DocumentViewerImpl::MakeWindow(const nsS
   // Create a view
   nsIView* view = mViewManager->CreateView(tbounds, containerView);
   if (!view)
     return NS_ERROR_OUT_OF_MEMORY;
 
   // pass in a native widget to be the parent widget ONLY if the view hierarchy will stand alone.
   // otherwise the view will find its own parent widget and "do the right thing" to
   // establish a parent/child widget relationship
-  rv = view->CreateWidget(kWidgetCID, nsnull,
-                          containerView != nsnull ? nsnull : mParentWidget->GetNativeData(NS_NATIVE_WIDGET),
+  nsWidgetInitData initData;
+  nsWidgetInitData* initDataPtr;
+  if (!mParentWidget) {
+    initDataPtr = &initData;
+    initData.mWindowType = eWindowType_invisible;
+
+    initData.mContentType =
+      nsContentUtils::IsInChromeDocshell(mDocument) ?
+        eContentTypeUI : eContentTypeContent;
+  } else {
+    initDataPtr = nsnull;
+  }
+  rv = view->CreateWidget(kWidgetCID, initDataPtr,
+                          (containerView != nsnull || !mParentWidget) ?
+                            nsnull : mParentWidget->GetNativeData(NS_NATIVE_WIDGET),
                           PR_TRUE, PR_FALSE);
   if (NS_FAILED(rv))
     return rv;
 
   // Setup hierarchical relationship in view manager
   mViewManager->SetRootView(view);
 
   mWindow = view->GetWidget();
@@ -2268,22 +2284,24 @@ DocumentViewerImpl::MakeWindow(const nsS
   // mWindow->SetFocus();
 
   return rv;
 }
 
 nsresult
 DocumentViewerImpl::CreateDeviceContext(nsIWidget* aWidget)
 {
-  NS_PRECONDITION(!mDeviceContext, "How come we're calling this?");
-  if (aWidget) {
-    mDeviceContext = do_CreateInstance(kDeviceContextCID);
-    NS_ENSURE_TRUE(mDeviceContext, NS_ERROR_FAILURE);
-    mDeviceContext->Init(aWidget->GetNativeData(NS_NATIVE_WIDGET));
-  }
+  NS_PRECONDITION(!mPresShell && !mPresContext && !mWindow,
+                  "This will screw up our existing presentation");
+  // Create a device context even if we already have one, since our widget
+  // might have changed.
+  mDeviceContext = do_CreateInstance(kDeviceContextCID);
+  NS_ENSURE_TRUE(mDeviceContext, NS_ERROR_FAILURE);
+  mDeviceContext->Init(aWidget ?
+                       aWidget->GetNativeData(NS_NATIVE_WIDGET) : nsnull);
   return NS_OK;
 }
 
 // Return the selection for the document. Note that text fields have their
 // own selection, which cannot be accessed with this method. Use
 // mPresShell->GetSelectionForCopy() instead.
 nsresult DocumentViewerImpl::GetDocumentSelection(nsISelection **aSelection)
 {
@@ -2757,18 +2775,16 @@ DocumentViewerImpl::GetAuthorStyleDisabl
     *aStyleDisabled = PR_FALSE;
   }
   return NS_OK;
 }
 
 NS_IMETHODIMP
 DocumentViewerImpl::GetDefaultCharacterSet(nsACString& aDefaultCharacterSet)
 {
-  NS_ENSURE_STATE(nsCOMPtr<nsISupports>(do_QueryReferent(mContainer)));
-
   if (mDefaultCharacterSet.IsEmpty())
   {
     const nsAdoptingString& defCharset =
       nsContentUtils::GetLocalizedStringPref("intl.charset.default");
 
     if (!defCharset.IsEmpty())
       LossyCopyUTF16toASCII(defCharset, mDefaultCharacterSet);
     else
@@ -3053,19 +3069,20 @@ NS_IMETHODIMP DocumentViewerImpl::GetBid
   }
   return NS_OK;
 }
 
 NS_IMETHODIMP DocumentViewerImpl::SizeToContent()
 {
    NS_ENSURE_TRUE(mDocument, NS_ERROR_NOT_AVAILABLE);
 
+   // Skip doing this on docshell-less documents for now
    nsCOMPtr<nsIDocShellTreeItem> docShellAsItem(do_QueryReferent(mContainer));
-   NS_ENSURE_TRUE(docShellAsItem, NS_ERROR_FAILURE);
-
+   NS_ENSURE_TRUE(docShellAsItem, NS_ERROR_NOT_AVAILABLE);
+   
    nsCOMPtr<nsIDocShellTreeItem> docShellParent;
    docShellAsItem->GetSameTypeParent(getter_AddRefs(docShellParent));
 
    // It's only valid to access this from a top frame.  Doesn't work from
    // sub-frames.
    NS_ENSURE_TRUE(!docShellParent, NS_ERROR_FAILURE);
 
    nsCOMPtr<nsIPresShell> presShell;
--- a/layout/base/nsPresShell.cpp
+++ b/layout/base/nsPresShell.cpp
@@ -1799,59 +1799,45 @@ PresShell::SetPreferenceStyleRules(PRBoo
   // DocumentViewerImpl::Close()).
 
   if (!window) {
     return NS_ERROR_NULL_POINTER;
   } 
 
   NS_PRECONDITION(mPresContext, "presContext cannot be null");
   if (mPresContext) {
-    nsresult result = NS_OK;
-
     // first, make sure this is not a chrome shell 
-    nsCOMPtr<nsISupports> container = mPresContext->GetContainer();
-    if (container) {
-      nsCOMPtr<nsIDocShellTreeItem> docShell(do_QueryInterface(container, &result));
-      if (NS_SUCCEEDED(result) && docShell){
-        PRInt32 docShellType;
-        result = docShell->GetItemType(&docShellType);
-        if (NS_SUCCEEDED(result)){
-          if (nsIDocShellTreeItem::typeChrome == docShellType){
-            return NS_OK;
-          }
-        }      
-      }
+    if (nsContentUtils::IsInChromeDocshell(mDocument)) {
+      return NS_OK;
+    }
+
+#ifdef DEBUG_attinasi
+    printf("Setting Preference Style Rules:\n");
+#endif
+    // if here, we need to create rules for the prefs
+    // - this includes the background-color, the text-color,
+    //   the link color, the visited link color and the link-underlining
+    
+    // first clear any exising rules
+    nsresult result = ClearPreferenceStyleRules();
+      
+    // now the link rules (must come after the color rules, or links will not be correct color!)
+    // XXX - when there is both an override and agent pref stylesheet this won't matter,
+    //       as the color rules will be overrides and the links rules will be agent
+    if (NS_SUCCEEDED(result)) {
+      result = SetPrefLinkRules();
     }
     if (NS_SUCCEEDED(result)) {
-    
-#ifdef DEBUG_attinasi
-      printf("Setting Preference Style Rules:\n");
-#endif
-      // if here, we need to create rules for the prefs
-      // - this includes the background-color, the text-color,
-      //   the link color, the visited link color and the link-underlining
-    
-      // first clear any exising rules
-      result = ClearPreferenceStyleRules();
-      
-      // now the link rules (must come after the color rules, or links will not be correct color!)
-      // XXX - when there is both an override and agent pref stylesheet this won't matter,
-      //       as the color rules will be overrides and the links rules will be agent
-      if (NS_SUCCEEDED(result)) {
-        result = SetPrefLinkRules();
-      }
-      if (NS_SUCCEEDED(result)) {
-        result = SetPrefFocusRules();
-      }
-      if (NS_SUCCEEDED(result)) {
-        result = SetPrefNoScriptRule();
-      }
-      if (NS_SUCCEEDED(result)) {
-        result = SetPrefNoFramesRule();
-      }
+      result = SetPrefFocusRules();
+    }
+    if (NS_SUCCEEDED(result)) {
+      result = SetPrefNoScriptRule();
+    }
+    if (NS_SUCCEEDED(result)) {
+      result = SetPrefNoFramesRule();
     }
 #ifdef DEBUG_attinasi
     printf( "Preference Style Rules set: error=%ld\n", (long)result);
 #endif
 
     // Note that this method never needs to force any calculation; the caller
     // will recalculate style if needed
 
@@ -5483,17 +5469,21 @@ nsresult PresShell::RetargetEventToParen
   nsCOMPtr<nsIPresShell> kungFuDeathGrip(this);
   nsCOMPtr<nsISupports> container = mPresContext->GetContainer();
   if (!container)
     container = do_QueryReferent(mForwardingContainer);
 
   // Now, find the parent pres shell and send the event there
   nsCOMPtr<nsIDocShellTreeItem> treeItem = 
     do_QueryInterface(container);
-  NS_ASSERTION(treeItem, "No tree item for container.");
+  if (!treeItem) {
+    // Might have gone away, or never been around to start with
+    return NS_ERROR_FAILURE;
+  }
+  
   nsCOMPtr<nsIDocShellTreeItem> parentTreeItem;
   treeItem->GetParent(getter_AddRefs(parentTreeItem));
   nsCOMPtr<nsIDocShell> parentDocShell = 
     do_QueryInterface(parentTreeItem);
   if (!parentDocShell || treeItem == parentTreeItem) {
     return NS_ERROR_FAILURE;
   }
 
--- a/layout/forms/nsFileControlFrame.cpp
+++ b/layout/forms/nsFileControlFrame.cpp
@@ -301,17 +301,22 @@ nsFileControlFrame::MouseListener::Mouse
   nsXPIDLString title;
   nsContentUtils::GetLocalizedString(nsContentUtils::eFORMS_PROPERTIES,
                                      "FileUpload", title);
 
   nsCOMPtr<nsIFilePicker> filePicker = do_CreateInstance("@mozilla.org/filepicker;1");
   if (!filePicker)
     return NS_ERROR_FAILURE;
 
-  result = filePicker->Init(doc->GetWindow(), title, nsIFilePicker::modeOpen);
+  nsPIDOMWindow* win = doc->GetWindow();
+  if (!win) {
+    return NS_ERROR_FAILURE;
+  }
+
+  result = filePicker->Init(win, title, nsIFilePicker::modeOpen);
   if (NS_FAILED(result))
     return result;
 
   // Set filter "All Files"
   filePicker->AppendFilters(nsIFilePicker::filterAll);
 
   // Set default directry and filename
   nsAutoString defaultName;
--- a/layout/style/nsMediaFeatures.cpp
+++ b/layout/style/nsMediaFeatures.cpp
@@ -79,19 +79,23 @@ GetHeight(nsPresContext* aPresContext, n
 
 static nsIDeviceContext*
 GetDeviceContextFor(nsPresContext* aPresContext)
 {
   // Do this dance rather than aPresContext->DeviceContext() to get
   // things right in multi-monitor situations.
   // (It's not clear if this is really needed for GetDepth and GetColor,
   // but do it anyway.)
-  return nsLayoutUtils::GetDeviceContextForScreenInfo(
+  nsIDeviceContext* ctx = nsLayoutUtils::GetDeviceContextForScreenInfo(
     nsCOMPtr<nsIDocShell>(do_QueryInterface(
       nsCOMPtr<nsISupports>(aPresContext->GetContainer()))));
+  if (!ctx) {
+    ctx = aPresContext->DeviceContext();
+  }
+  return ctx;
 }
 
 PR_STATIC_CALLBACK(nsresult)
 GetDeviceWidth(nsPresContext* aPresContext, nsCSSValue& aResult)
 {
     // XXX: I'm not sure if this is really the right thing for print:
     // do we want to include unprintable areas / page margins?
     nsIDeviceContext *dx = GetDeviceContextFor(aPresContext);
--- a/layout/xul/base/src/nsTitleBarFrame.cpp
+++ b/layout/xul/base/src/nsTitleBarFrame.cpp
@@ -173,17 +173,19 @@ nsTitleBarFrame::HandleEvent(nsPresConte
              GetWidget(getter_AddRefs(widget));
            nsRect bounds;
            widget->GetScreenBounds(bounds);
            widget->Move(bounds.x + nsMoveBy.x, bounds.y + nsMoveBy.y);
          }
          else {
            nsIPresShell* presShell = aPresContext->PresShell();
            nsPIDOMWindow *window = presShell->GetDocument()->GetWindow();
-           window->MoveBy(nsMoveBy.x, nsMoveBy.y);
+           if (window) {
+             window->MoveBy(nsMoveBy.x, nsMoveBy.y);
+           }
          }
 
          *aEventStatus = nsEventStatus_eConsumeNoDefault;
 
          doDefault = PR_FALSE;
        }
      }
      break;