1 | /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
---|
2 | /* ***** BEGIN LICENSE BLOCK ***** |
---|
3 | * Version: NPL 1.1/GPL 2.0/LGPL 2.1 |
---|
4 | * |
---|
5 | * The contents of this file are subject to the Netscape Public License |
---|
6 | * Version 1.1 (the "License"); you may not use this file except in |
---|
7 | * compliance with the License. You may obtain a copy of the License at |
---|
8 | * http://www.mozilla.org/NPL/ |
---|
9 | * |
---|
10 | * Software distributed under the License is distributed on an "AS IS" basis, |
---|
11 | * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License |
---|
12 | * for the specific language governing rights and limitations under the |
---|
13 | * License. |
---|
14 | * |
---|
15 | * The Original Code is mozilla.org code. |
---|
16 | * |
---|
17 | * The Initial Developer of the Original Code is |
---|
18 | * Netscape Communications Corporation. |
---|
19 | * Portions created by the Initial Developer are Copyright (C) 2001 |
---|
20 | * the Initial Developer. All Rights Reserved. |
---|
21 | * |
---|
22 | * Contributor(s): |
---|
23 | * |
---|
24 | * Alternatively, the contents of this file may be used under the terms of |
---|
25 | * either the GNU General Public License Version 2 or later (the "GPL"), or |
---|
26 | * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), |
---|
27 | * in which case the provisions of the GPL or the LGPL are applicable instead |
---|
28 | * of those above. If you wish to allow use of your version of this file only |
---|
29 | * under the terms of either the GPL or the LGPL, and not to allow others to |
---|
30 | * use your version of this file under the terms of the NPL, indicate your |
---|
31 | * decision by deleting the provisions above and replace them with the notice |
---|
32 | * and other provisions required by the GPL or the LGPL. If you do not delete |
---|
33 | * the provisions above, a recipient may use your version of this file under |
---|
34 | * the terms of any one of the NPL, the GPL or the LGPL. |
---|
35 | * |
---|
36 | * ***** END LICENSE BLOCK ***** */ |
---|
37 | |
---|
38 | /* There are several ways to open a new window in Mozilla: directly, using |
---|
39 | nsAppShellService; indirectly, using the Open method on an extant |
---|
40 | window, the OpenWindow method on the nsWindowWatcher service, and this |
---|
41 | WindowCreator. I think that's all of them, for petessake. But |
---|
42 | the conditions under which each should be used are definite, if |
---|
43 | not clear, and there is no overlap. |
---|
44 | |
---|
45 | Basically, you should never use nsAppShellService. That's the basic |
---|
46 | method that all others boil down to, and it creates partially initialized |
---|
47 | windows. Trust the other means of opening windows to use nsAppShellService |
---|
48 | and then finish the new window's initialization. nsAppShellService is |
---|
49 | also strictly a Mozilla-only service; it's unavailable (or should be) |
---|
50 | to embedding apps. So it's not merely inadvisable but also illegal |
---|
51 | for any code that may execute in an embedding context to use that service. |
---|
52 | |
---|
53 | Unless you're writing window opening code yourself, you want to use |
---|
54 | the Open method on an extant window, or lacking one of those, the |
---|
55 | OpenWindow method on the nsWindowWatcher service. (The former calls |
---|
56 | through to the latter.) Both methods are equally at home in Mozilla |
---|
57 | and embedding contexts. They differentiate between which kind of window |
---|
58 | to open in different ways, depending on whether there is an extant |
---|
59 | window. |
---|
60 | |
---|
61 | Lacking an extant window, it's this object, the nsWindowCreator, |
---|
62 | that allows new window creation and properly distinguishes between |
---|
63 | Mozilla and embedding contexts. This source file contains the |
---|
64 | Mozilla version, which calls through to nsAppShellService. |
---|
65 | */ |
---|
66 | |
---|
67 | #include "nsCOMPtr.h" |
---|
68 | #include "nsAppShellCIDs.h" |
---|
69 | #include "nsWidgetsCID.h" |
---|
70 | #include "nsWindowCreator.h" |
---|
71 | |
---|
72 | #include "nsIAppShell.h" |
---|
73 | #include "nsIAppShellService.h" |
---|
74 | #include "nsIInterfaceRequestor.h" |
---|
75 | #include "nsIInterfaceRequestorUtils.h" |
---|
76 | #include "nsIServiceManager.h" |
---|
77 | #include "nsIURI.h" |
---|
78 | #include "nsIXULWindow.h" |
---|
79 | #include "nsIWebBrowserChrome.h" |
---|
80 | |
---|
81 | static NS_DEFINE_CID(kAppShellServiceCID, NS_APPSHELL_SERVICE_CID); |
---|
82 | |
---|
83 | nsWindowCreator::nsWindowCreator() { |
---|
84 | } |
---|
85 | |
---|
86 | nsWindowCreator::~nsWindowCreator() { |
---|
87 | } |
---|
88 | |
---|
89 | NS_IMPL_ISUPPORTS2(nsWindowCreator, nsIWindowCreator, nsIWindowCreator2) |
---|
90 | |
---|
91 | NS_IMETHODIMP |
---|
92 | nsWindowCreator::CreateChromeWindow(nsIWebBrowserChrome *aParent, |
---|
93 | PRUint32 aChromeFlags, |
---|
94 | nsIWebBrowserChrome **_retval) |
---|
95 | { |
---|
96 | PRBool cancel; |
---|
97 | return CreateChromeWindow2(aParent, aChromeFlags, 0, 0, &cancel, _retval); |
---|
98 | } |
---|
99 | |
---|
100 | NS_IMETHODIMP |
---|
101 | nsWindowCreator::CreateChromeWindow2( nsIWebBrowserChrome *aParent, |
---|
102 | PRUint32 aChromeFlags, |
---|
103 | PRUint32 aContextFlags, |
---|
104 | nsIURI *aURI, |
---|
105 | PRBool *aCancel, |
---|
106 | nsIWebBrowserChrome **_retval) |
---|
107 | { |
---|
108 | NS_ENSURE_ARG_POINTER(aCancel); |
---|
109 | NS_ENSURE_ARG_POINTER(_retval); |
---|
110 | *aCancel = PR_FALSE; |
---|
111 | *_retval = 0; |
---|
112 | |
---|
113 | nsCOMPtr<nsIXULWindow> newWindow; |
---|
114 | |
---|
115 | if (aParent) { |
---|
116 | nsCOMPtr<nsIXULWindow> xulParent(do_GetInterface(aParent)); |
---|
117 | NS_ASSERTION(xulParent, "window created using non-XUL parent. that's unexpected, but may work."); |
---|
118 | |
---|
119 | if (xulParent) |
---|
120 | xulParent->CreateNewWindow(aChromeFlags, getter_AddRefs(newWindow)); |
---|
121 | // And if it fails, don't try again without a parent. It could fail |
---|
122 | // intentionally (bug 115969). |
---|
123 | } else { // try using basic methods: |
---|
124 | /* You really shouldn't be making dependent windows without a parent. |
---|
125 | But unparented modal (and therefore dependent) windows happen |
---|
126 | in our codebase, so we allow it after some bellyaching: */ |
---|
127 | if (aChromeFlags & nsIWebBrowserChrome::CHROME_DEPENDENT) |
---|
128 | NS_WARNING("dependent window created without a parent"); |
---|
129 | |
---|
130 | nsCOMPtr<nsIAppShellService> appShell(do_GetService(kAppShellServiceCID)); |
---|
131 | if (!appShell) |
---|
132 | return NS_ERROR_FAILURE; |
---|
133 | |
---|
134 | appShell->CreateTopLevelWindow(0, 0, PR_FALSE, PR_FALSE, |
---|
135 | aChromeFlags, nsIAppShellService::SIZE_TO_CONTENT, |
---|
136 | nsIAppShellService::SIZE_TO_CONTENT, getter_AddRefs(newWindow)); |
---|
137 | } |
---|
138 | |
---|
139 | // if anybody gave us anything to work with, use it |
---|
140 | if (newWindow) { |
---|
141 | newWindow->SetContextFlags(aContextFlags); |
---|
142 | nsCOMPtr<nsIInterfaceRequestor> thing(do_QueryInterface(newWindow)); |
---|
143 | if (thing) |
---|
144 | thing->GetInterface(NS_GET_IID(nsIWebBrowserChrome), (void **) _retval); |
---|
145 | } |
---|
146 | |
---|
147 | return *_retval ? NS_OK : NS_ERROR_FAILURE; |
---|
148 | } |
---|