/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is mozilla.org code. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 2002 * the Initial Developer. All Rights Reserved. * * Contributor(s): * Conrad Carlen * * Alternatively, the contents of this file may be used under the terms of * either the GNU General Public License Version 2 or later (the "GPL"), or * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), * in which case the provisions of the GPL or the LGPL are applicable instead * of those above. If you wish to allow use of your version of this file only * under the terms of either the GPL or the LGPL, and not to allow others to * use your version of this file under the terms of the MPL, indicate your * decision by deleting the provisions above and replace them with the notice * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ #include "CWindowCreator.h" #include "nsIWindowWatcher.h" #include "nsServiceManagerUtils.h" #include "nsIWebBrowserSetup.h" #include "nsIPrefBranch.h" #include "nsIURI.h" #include "CBrowserShell.h" #include "CBrowserWindow.h" #include "CPrintAttachment.h" #include "ApplIDs.h" // --------------------------------------------------------------------------- // CWindowCreator // --------------------------------------------------------------------------- NS_IMPL_ISUPPORTS2(CWindowCreator, nsIWindowCreator, nsIWindowCreator2) CWindowCreator::CWindowCreator() { } CWindowCreator::~CWindowCreator() { } NS_IMETHODIMP CWindowCreator::CreateChromeWindow(nsIWebBrowserChrome *aParent, PRUint32 aChromeFlags, nsIWebBrowserChrome **_retval) { NS_ENSURE_ARG_POINTER(_retval); *_retval = 0; // we're ignoring aParent, // but since windows on the Mac don't have parents anyway... try { LWindow *theWindow = CreateWindowInternal(aChromeFlags, PR_FALSE, -1, -1); CBrowserShell *browser = dynamic_cast(theWindow->FindPaneByID(CBrowserShell::paneID_MainBrowser)); ThrowIfNil_(browser); browser->GetWebBrowserChrome(_retval); } catch(...) { return NS_ERROR_FAILURE; } return NS_OK; } NS_IMETHODIMP CWindowCreator::CreateChromeWindow2(nsIWebBrowserChrome *parent, PRUint32 chromeFlags, PRUint32 contextFlags, nsIURI *aURI, PRBool *aCancel, nsIWebBrowserChrome **_retval) { NS_ENSURE_ARG_POINTER(aCancel); *aCancel = PR_FALSE; if (contextFlags & nsIWindowCreator2::PARENT_IS_LOADING_OR_RUNNING_TIMEOUT) { nsCOMPtr prefs(do_GetService("@mozilla.org/preferences-service;1")); if (prefs) { PRBool showBlocker = PR_TRUE; prefs->GetBoolPref("browser.popups.showPopupBlocker", &showBlocker); if (showBlocker) { short itemHit; AlertStdAlertParamRec pb; LStr255 msgString(STRx_StdAlertStrings, str_OpeningPopupWindow); LStr255 explainString(STRx_StdAlertStrings, str_OpeningPopupWindowExp); LStr255 defaultButtonText(STRx_StdButtonTitles, str_DenyAll); LStr255 cancelButtonText(STRx_StdButtonTitles, str_Allow); pb.movable = false; pb.helpButton = false; pb.filterProc = nil; pb.defaultText = defaultButtonText; pb.cancelText = cancelButtonText; pb.otherText = nil; pb.defaultButton = kStdOkItemIndex; pb.cancelButton = kStdCancelItemIndex; pb.position = kWindowAlertPositionParentWindowScreen; ::StandardAlert(kAlertStopAlert, msgString, explainString, &pb, &itemHit); // This a one-time (for the life of prefs.js) alert prefs->SetBoolPref("browser.popups.showPopupBlocker", PR_FALSE); if (itemHit == kAlertStdAlertOKButton) { // Also, if these prefs are set, the DOM itself will prevent future // popups from being opened and our window creator won't even get // called. If you wanted to filter each request, don't set these // prefs. For this purpose, it's what we want, though. prefs->SetBoolPref("dom.disable_open_during_load", PR_TRUE); prefs->SetIntPref("dom.disable_open_click_delay", 1000); return NS_ERROR_FAILURE; } } } } return CreateChromeWindow(parent, chromeFlags, _retval); } /* InitializeWindowCreator creates and hands off an object with a callback to a window creation function. This will be used by Gecko C++ code (never JS) to create new windows when no previous window is handy to begin with. This is done in a few exceptional cases, like PSM code. Failure to set this callback will only disable the ability to create new windows under these circumstances. */ nsresult CWindowCreator::Initialize() { // Create a CWindowCreator and give it to the WindowWatcher service // The WindowWatcher service will own it so we don't keep a ref. CWindowCreator *windowCreator = new CWindowCreator; if (!windowCreator) return NS_ERROR_FAILURE; nsCOMPtr wwatch(do_GetService(NS_WINDOWWATCHER_CONTRACTID)); if (!wwatch) return NS_ERROR_FAILURE; return wwatch->SetWindowCreator(windowCreator); } LWindow* CWindowCreator::CreateWindowInternal(PRUint32 inChromeFlags, PRBool enablePrinting, PRInt32 width, PRInt32 height) { const SInt16 kStatusBarHeight = 16; const SDimension16 kMinimumWindowDimension = { 300, 150 }; const SInt16 kStdSizeVertMargin = 100; LWindow *theWindow; PRUint32 chromeFlags; if (inChromeFlags == nsIWebBrowserChrome::CHROME_DEFAULT) chromeFlags = nsIWebBrowserChrome::CHROME_WINDOW_RESIZE | nsIWebBrowserChrome::CHROME_WINDOW_CLOSE | nsIWebBrowserChrome::CHROME_TOOLBAR | nsIWebBrowserChrome::CHROME_STATUSBAR; else chromeFlags = inChromeFlags; // Bounds - Set to an arbitrary rect - we'll size it after all the subviews are in. Rect globalBounds; globalBounds.left = 4; globalBounds.top = 42; globalBounds.right = globalBounds.left + 600; globalBounds.bottom = globalBounds.top + 400; // ProcID and attributes short windowDefProc; UInt32 windowAttrs = (windAttr_Enabled | windAttr_Targetable); if (chromeFlags & nsIWebBrowserChrome::CHROME_OPENAS_DIALOG) { if (chromeFlags & nsIWebBrowserChrome::CHROME_TITLEBAR) { windowDefProc = kWindowMovableModalDialogProc; windowAttrs |= windAttr_TitleBar; } else windowDefProc = kWindowModalDialogProc; } else { if (chromeFlags & nsIWebBrowserChrome::CHROME_WINDOW_RESIZE) { windowDefProc = kWindowGrowDocumentProc; windowAttrs |= windAttr_Resizable; windowAttrs |= windAttr_Zoomable; } else windowDefProc = kWindowDocumentProc; if (chromeFlags & nsIWebBrowserChrome::CHROME_WINDOW_CLOSE) windowAttrs |= windAttr_CloseBox; } if (chromeFlags & nsIWebBrowserChrome::CHROME_MODAL) windowAttrs |= windAttr_Modal; else windowAttrs |= windAttr_Regular; theWindow = new CBrowserWindow(LCommander::GetTopCommander(), globalBounds, "\p", windowDefProc, windowAttrs, window_InFront); ThrowIfNil_(theWindow); if (windowAttrs & windAttr_Resizable) { Rect stdBounds, minMaxBounds; SDimension16 stdSize; theWindow->CalcStandardBounds(stdBounds); stdSize.width = stdBounds.right - stdBounds.left; stdSize.height = stdBounds.bottom - stdBounds.top; stdSize.width -= kStdSizeVertMargin; // Leave a vertical strip of desktop exposed theWindow->SetStandardSize(stdSize); minMaxBounds.left = kMinimumWindowDimension.width; minMaxBounds.top = kMinimumWindowDimension.height; Rect deskRect; ::GetRegionBounds(::GetGrayRgn(), &deskRect); minMaxBounds.left = kMinimumWindowDimension.width; minMaxBounds.top = kMinimumWindowDimension.height; minMaxBounds.right = deskRect.right - deskRect.left; minMaxBounds.bottom = deskRect.bottom - deskRect.top; theWindow->SetMinMaxSize(minMaxBounds); } SDimension16 windowSize, toolBarSize; theWindow->GetFrameSize(windowSize); if (chromeFlags & nsIWebBrowserChrome::CHROME_TOOLBAR) { LView::SetDefaultView(theWindow); LCommander::SetDefaultCommander(theWindow); LAttachable::SetDefaultAttachable(nil); LView *toolBarView = static_cast(UReanimator::ReadObjects(ResType_PPob, 131)); ThrowIfNil_(toolBarView); toolBarView->GetFrameSize(toolBarSize); toolBarView->PlaceInSuperFrameAt(0, 0, false); toolBarSize.width = windowSize.width; toolBarView->ResizeFrameTo(toolBarSize.width, toolBarSize.height, false); } SPaneInfo aPaneInfo; SViewInfo aViewInfo; aPaneInfo.paneID = CBrowserShell::paneID_MainBrowser; aPaneInfo.width = windowSize.width; aPaneInfo.height = windowSize.height; if (chromeFlags & nsIWebBrowserChrome::CHROME_TOOLBAR) aPaneInfo.height -= toolBarSize.height; if (chromeFlags & nsIWebBrowserChrome::CHROME_STATUSBAR) aPaneInfo.height -= kStatusBarHeight - 1; aPaneInfo.visible = true; aPaneInfo.enabled = true; aPaneInfo.bindings.left = true; aPaneInfo.bindings.top = true; aPaneInfo.bindings.right = true; aPaneInfo.bindings.bottom = true; aPaneInfo.left = 0; aPaneInfo.top = (chromeFlags & nsIWebBrowserChrome::CHROME_TOOLBAR) ? toolBarSize.height : 0; aPaneInfo.userCon = 0; aPaneInfo.superView = theWindow; aViewInfo.imageSize.width = 0; aViewInfo.imageSize.height = 0; aViewInfo.scrollPos.h = aViewInfo.scrollPos.v = 0; aViewInfo.scrollUnit.h = aViewInfo.scrollUnit.v = 1; aViewInfo.reconcileOverhang = 0; CBrowserShell *aShell = new CBrowserShell(aPaneInfo, aViewInfo, chromeFlags, PR_TRUE); ThrowIfNil_(aShell); aShell->AddAttachments(); aShell->PutInside(theWindow, false); if (chromeFlags & nsIWebBrowserChrome::CHROME_OPENAS_CHROME) { nsCOMPtr browser; aShell->GetWebBrowser(getter_AddRefs(browser)); nsCOMPtr setup(do_QueryInterface(browser)); if (setup) setup->SetProperty(nsIWebBrowserSetup::SETUP_IS_CHROME_WRAPPER, PR_TRUE); } if (chromeFlags & nsIWebBrowserChrome::CHROME_STATUSBAR) { LView::SetDefaultView(theWindow); LCommander::SetDefaultCommander(theWindow); LAttachable::SetDefaultAttachable(nil); LView *statusView = static_cast(UReanimator::ReadObjects(ResType_PPob, 130)); ThrowIfNil_(statusView); statusView->PlaceInSuperFrameAt(0, windowSize.height - kStatusBarHeight + 1, false); statusView->ResizeFrameTo(windowSize.width - 15, kStatusBarHeight, false); } if (enablePrinting) { CPrintAttachment *printAttachment = new CPrintAttachment(CBrowserShell::paneID_MainBrowser); ThrowIfNil_(printAttachment); theWindow->AddAttachment(printAttachment); } // Now the window is constructed... theWindow->FinishCreate(); Rect theBounds; theWindow->GetGlobalBounds(theBounds); if (width == -1) width = theBounds.right - theBounds.left; if (height == -1) height = theBounds.bottom - theBounds.top; theWindow->ResizeWindowTo(width, height); return theWindow; }