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

This commit is contained in:
Boris Zbarsky 2008-09-28 15:14:28 -04:00
parent fd441c1339
commit d674c8ca02
11 changed files with 146 additions and 93 deletions

View File

@ -807,6 +807,13 @@ public:
*/
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
*/

View File

@ -2903,6 +2903,24 @@ nsContentUtils::IsChromeDoc(nsIDocument *aDocument)
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()

View File

@ -5727,9 +5727,7 @@ nsDocument::FlushPendingNotifications(mozFlushType 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;
}

View File

@ -6282,6 +6282,9 @@ nsEventStateManager::ShiftFocusByDoc(PRBool aForward)
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

View File

@ -709,10 +709,6 @@ nsHTMLDocument::StartDocumentLoad(const char* aCommand,
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
@ -722,11 +718,17 @@ nsHTMLDocument::StartDocumentLoad(const char* aCommand,
// 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;
@ -747,7 +749,9 @@ nsHTMLDocument::StartDocumentLoad(const char* aCommand,
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 {
@ -784,6 +788,11 @@ nsHTMLDocument::StartDocumentLoad(const char* aCommand,
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);

View File

@ -423,7 +423,7 @@ nsFocusController::GetWindowFromDocument(nsIDOMDocument* aDocument)
{
nsCOMPtr<nsIDocument> doc = do_QueryInterface(aDocument);
if (!doc)
return NS_OK;
return nsnull;
return doc->GetWindow();
}

View File

@ -433,7 +433,7 @@ protected:
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.
@ -958,14 +958,11 @@ DocumentViewerImpl::LoadComplete(nsresult aStatus)
// 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;
@ -1241,12 +1238,6 @@ 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);
@ -1262,11 +1253,13 @@ DocumentViewerImpl::Open(nsISupports *aState, nsISHEntry *aSHEntry)
// 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();
@ -1873,11 +1866,11 @@ DocumentViewerImpl::Show(void)
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);
@ -1894,7 +1887,12 @@ DocumentViewerImpl::Show(void)
}
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)));
@ -2098,9 +2096,11 @@ DocumentViewerImpl::CreateStyleSet(nsIDocument* aDocument,
// 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();
@ -2119,7 +2119,9 @@ DocumentViewerImpl::CreateStyleSet(nsIDocument* aDocument,
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));
@ -2209,7 +2211,8 @@ DocumentViewerImpl::MakeWindow(const nsSize& aSize)
// 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
@ -2251,8 +2254,21 @@ DocumentViewerImpl::MakeWindow(const nsSize& aSize)
// 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;
@ -2273,12 +2289,14 @@ DocumentViewerImpl::MakeWindow(const nsSize& aSize)
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;
}
@ -2762,8 +2780,6 @@ DocumentViewerImpl::GetAuthorStyleDisabled(PRBool* aStyleDisabled)
NS_IMETHODIMP
DocumentViewerImpl::GetDefaultCharacterSet(nsACString& aDefaultCharacterSet)
{
NS_ENSURE_STATE(nsCOMPtr<nsISupports>(do_QueryReferent(mContainer)));
if (mDefaultCharacterSet.IsEmpty())
{
const nsAdoptingString& defCharset =
@ -3058,9 +3074,10 @@ 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));

View File

@ -1804,49 +1804,35 @@ PresShell::SetPreferenceStyleRules(PRBool aForceReflow)
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);
@ -5488,7 +5474,11 @@ nsresult PresShell::RetargetEventToParent(nsGUIEvent* aEvent,
// 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 =

View File

@ -306,7 +306,12 @@ nsFileControlFrame::MouseListener::MouseClick(nsIDOMEvent* aMouseEvent)
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;

View File

@ -84,9 +84,13 @@ GetDeviceContextFor(nsPresContext* aPresContext)
// 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)

View File

@ -178,7 +178,9 @@ nsTitleBarFrame::HandleEvent(nsPresContext* aPresContext,
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;