1 | /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- |
1 | /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- |
2 | * |
2 | * |
3 | * The contents of this file are subject to the Mozilla Public |
3 | * The contents of this file are subject to the Mozilla Public |
4 | * License Version 1.1 (the "License"); you may not use this file |
4 | * License Version 1.1 (the "License"); you may not use this file |
5 | * except in compliance with the License. You may obtain a copy of |
5 | * except in compliance with the License. You may obtain a copy of |
6 | * the License at http://www.mozilla.org/MPL/ |
6 | * the License at http://www.mozilla.org/MPL/ |
7 | * |
7 | * |
8 | * Software distributed under the License is distributed on an "AS |
8 | * Software distributed under the License is distributed on an "AS |
9 | * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or |
9 | * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or |
10 | * implied. See the License for the specific language governing |
10 | * implied. See the License for the specific language governing |
11 | * rights and limitations under the License. |
11 | * rights and limitations under the License. |
12 | * |
12 | * |
13 | * The Original Code is the Mozilla browser. |
13 | * The Original Code is the Mozilla browser. |
14 | * |
14 | * |
15 | * The Initial Developer of the Original Code is Netscape |
15 | * The Initial Developer of the Original Code is Netscape |
34 | */ |
21 | */ |
35 | |
22 | |
36 | #include "nsDocShell.h" |
23 | #include "nsDocShell.h" |
37 | #include "nsDSURIContentListener.h" |
24 | #include "nsDSURIContentListener.h" |
38 | #include "nsIChannel.h" |
25 | #include "nsIChannel.h" |
39 | #include "nsXPIDLString.h" |
26 | #include "nsXPIDLString.h" |
40 | #include "nsIServiceManager.h" |
27 | #include "nsIServiceManager.h" |
41 | #include "nsIDOMWindowInternal.h" |
28 | #include "nsIDOMWindowInternal.h" |
42 | |
29 | |
43 | //***************************************************************************** |
30 | //***************************************************************************** |
44 | //*** nsDSURIContentListener: Object Management |
31 | //*** nsDSURIContentListener: Object Management |
45 | //***************************************************************************** |
32 | //***************************************************************************** |
46 | |
33 | |
47 | nsDSURIContentListener::nsDSURIContentListener() : mDocShell(nsnull), |
34 | nsDSURIContentListener::nsDSURIContentListener() : mDocShell(nsnull), |
48 | mParentContentListener(nsnull) |
35 | mParentContentListener(nsnull) |
49 | { |
36 | { |
50 | } |
37 | } |
51 | |
38 | |
52 | nsDSURIContentListener::~nsDSURIContentListener() |
39 | nsDSURIContentListener::~nsDSURIContentListener() |
53 | { |
40 | { |
54 | } |
41 | } |
55 | |
42 | |
56 | nsresult |
43 | nsresult |
57 | nsDSURIContentListener::Init() |
44 | nsDSURIContentListener::Init() |
58 | { |
45 | { |
59 | nsresult rv = NS_OK; |
46 | nsresult rv = NS_OK; |
60 | mCatMgr = do_GetService(NS_CATEGORYMANAGER_CONTRACTID, &rv); |
47 | mCatMgr = do_GetService(NS_CATEGORYMANAGER_CONTRACTID, &rv); |
61 | NS_ENSURE_SUCCESS(rv, rv); |
48 | NS_ENSURE_SUCCESS(rv, rv); |
62 | return rv; |
49 | return rv; |
63 | } |
50 | } |
64 | |
51 | |
65 | |
52 | |
66 | //***************************************************************************** |
53 | //***************************************************************************** |
67 | // nsDSURIContentListener::nsISupports |
54 | // nsDSURIContentListener::nsISupports |
68 | //***************************************************************************** |
55 | //***************************************************************************** |
69 | |
56 | |
70 | NS_IMPL_THREADSAFE_ADDREF(nsDSURIContentListener) |
57 | NS_IMPL_THREADSAFE_ADDREF(nsDSURIContentListener) |
71 | NS_IMPL_THREADSAFE_RELEASE(nsDSURIContentListener) |
58 | NS_IMPL_THREADSAFE_RELEASE(nsDSURIContentListener) |
72 | |
59 | |
73 | NS_INTERFACE_MAP_BEGIN(nsDSURIContentListener) |
60 | NS_INTERFACE_MAP_BEGIN(nsDSURIContentListener) |
74 | NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIURIContentListener) |
61 | NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIURIContentListener) |
75 | NS_INTERFACE_MAP_ENTRY(nsIURIContentListener) |
62 | NS_INTERFACE_MAP_ENTRY(nsIURIContentListener) |
76 | NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference) |
63 | NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference) |
77 | NS_INTERFACE_MAP_END |
64 | NS_INTERFACE_MAP_END |
78 | |
65 | |
79 | //***************************************************************************** |
66 | //***************************************************************************** |
80 | // nsDSURIContentListener::nsIURIContentListener |
67 | // nsDSURIContentListener::nsIURIContentListener |
81 | //***************************************************************************** |
68 | //***************************************************************************** |
82 | |
69 | |
83 | NS_IMETHODIMP |
70 | NS_IMETHODIMP |
84 | nsDSURIContentListener::OnStartURIOpen(nsIURI* aURI, PRBool* aAbortOpen) |
71 | nsDSURIContentListener::OnStartURIOpen(nsIURI* aURI, PRBool* aAbortOpen) |
85 | { |
72 | { |
86 | nsCOMPtr<nsIURIContentListener> parentListener; |
73 | nsCOMPtr<nsIURIContentListener> parentListener; |
87 | GetParentContentListener(getter_AddRefs(parentListener)); |
74 | GetParentContentListener(getter_AddRefs(parentListener)); |
96 | |
77 | |
97 | return NS_OK; |
78 | return NS_OK; |
98 | } |
79 | } |
99 | |
80 | |
100 | NS_IMETHODIMP |
81 | NS_IMETHODIMP |
101 | nsDSURIContentListener::DoContent(const char* aContentType, |
82 | nsDSURIContentListener::DoContent(const char* aContentType, |
102 | PRBool aIsContentPreferred, |
83 | PRBool aIsContentPreferred, |
103 | nsIRequest* request, |
84 | nsIRequest* request, |
104 | nsIStreamListener** aContentHandler, |
85 | nsIStreamListener** aContentHandler, |
105 | PRBool* aAbortProcess) |
86 | PRBool* aAbortProcess) |
106 | { |
87 | { |
107 | nsresult rv; |
88 | nsresult rv; |
108 | NS_ENSURE_ARG_POINTER(aContentHandler); |
89 | NS_ENSURE_ARG_POINTER(aContentHandler); |
109 | NS_ENSURE_TRUE(mDocShell, NS_ERROR_FAILURE); |
90 | NS_ENSURE_TRUE(mDocShell, NS_ERROR_FAILURE); |
110 | if(aAbortProcess) |
91 | if(aAbortProcess) |
111 | *aAbortProcess = PR_FALSE; |
92 | *aAbortProcess = PR_FALSE; |
112 | |
93 | |
113 | // determine if the channel has just been retargeted to us... |
94 | // determine if the channel has just been retargeted to us... |
114 | nsLoadFlags loadFlags = 0; |
95 | nsLoadFlags loadFlags = 0; |
115 | nsCOMPtr<nsIChannel> aOpenedChannel = do_QueryInterface(request); |
96 | nsCOMPtr<nsIChannel> aOpenedChannel = do_QueryInterface(request); |
116 | |
97 | |
117 | if (aOpenedChannel) |
98 | if (aOpenedChannel) |
118 | aOpenedChannel->GetLoadFlags(&loadFlags); |
99 | aOpenedChannel->GetLoadFlags(&loadFlags); |
119 | |
100 | |
120 | if(loadFlags & nsIChannel::LOAD_RETARGETED_DOCUMENT_URI) |
101 | if(loadFlags & nsIChannel::LOAD_RETARGETED_DOCUMENT_URI) |
121 | { |
102 | { |
122 | // XXX: Why does this not stop the content too? |
103 | // XXX: Why does this not stop the content too? |
123 | mDocShell->Stop(nsIWebNavigation::STOP_NETWORK); |
104 | mDocShell->Stop(nsIWebNavigation::STOP_NETWORK); |
124 | |
105 | |
125 | mDocShell->SetLoadType(aIsContentPreferred ? LOAD_LINK : LOAD_NORMAL); |
106 | mDocShell->SetLoadType(aIsContentPreferred ? LOAD_LINK : LOAD_NORMAL); |
126 | } |
107 | } |
127 | |
108 | |
128 | rv = mDocShell->CreateContentViewer(aContentType, request, aContentHandler); |
109 | rv = mDocShell->CreateContentViewer(aContentType, request, aContentHandler); |
129 | if (NS_FAILED(rv)) { |
110 | if (NS_FAILED(rv)) { |
130 | // it's okay if we don't know how to handle the content |
111 | // it's okay if we don't know how to handle the content |
131 | return NS_OK; |
112 | return NS_OK; |
132 | } |
113 | } |
133 | |
114 | |
134 | if (loadFlags & nsIChannel::LOAD_RETARGETED_DOCUMENT_URI) { |
115 | if (loadFlags & nsIChannel::LOAD_RETARGETED_DOCUMENT_URI) { |
135 | nsCOMPtr<nsIDOMWindowInternal> domWindow = do_GetInterface(NS_STATIC_CAST(nsIDocShell*, mDocShell)); |
116 | nsCOMPtr<nsIDOMWindowInternal> domWindow = do_GetInterface(NS_STATIC_CAST(nsIDocShell*, mDocShell)); |
136 | NS_ENSURE_TRUE(domWindow, NS_ERROR_FAILURE); |
117 | NS_ENSURE_TRUE(domWindow, NS_ERROR_FAILURE); |
137 | domWindow->Focus(); |
118 | domWindow->Focus(); |
138 | } |
119 | } |
139 | |
120 | |
140 | return NS_OK; |
121 | return NS_OK; |
141 | } |
122 | } |
142 | |
123 | |
143 | NS_IMETHODIMP |
124 | NS_IMETHODIMP |
144 | nsDSURIContentListener::IsPreferred(const char* aContentType, |
125 | nsDSURIContentListener::IsPreferred(const char* aContentType, |
145 | char ** aDesiredContentType, |
126 | char ** aDesiredContentType, |
146 | PRBool* aCanHandle) |
127 | PRBool* aCanHandle) |
147 | { |
128 | { |
148 | NS_ENSURE_ARG_POINTER(aCanHandle); |
129 | NS_ENSURE_ARG_POINTER(aCanHandle); |
149 | NS_ENSURE_ARG_POINTER(aDesiredContentType); |
130 | NS_ENSURE_ARG_POINTER(aDesiredContentType); |
150 | |
131 | |
151 | // the docshell has no idea if it is the preferred content provider or not. |
132 | // the docshell has no idea if it is the preferred content provider or not. |
152 | // It needs to ask it's parent if it is the preferred content handler or not... |
133 | // It needs to ask it's parent if it is the preferred content handler or not... |
153 | |
134 | |
154 | nsCOMPtr<nsIURIContentListener> parentListener; |
135 | nsCOMPtr<nsIURIContentListener> parentListener; |
155 | GetParentContentListener(getter_AddRefs(parentListener)); |
136 | GetParentContentListener(getter_AddRefs(parentListener)); |
156 | if (parentListener) { |
137 | if (parentListener) { |
164 | } |
141 | } |
165 | // we used to return false here if we didn't have a parent properly |
142 | // we used to return false here if we didn't have a parent properly |
166 | // registered at the top of the docshell hierarchy to dictate what |
143 | // registered at the top of the docshell hierarchy to dictate what |
167 | // content types this docshell should be a preferred handler for. But |
144 | // content types this docshell should be a preferred handler for. But |
168 | // this really makes it hard for developers using iframe or browser tags |
145 | // this really makes it hard for developers using iframe or browser tags |
169 | // because then they need to make sure they implement |
146 | // because then they need to make sure they implement |
170 | // nsIURIContentListener otherwise all link clicks would get sent to |
147 | // nsIURIContentListener otherwise all link clicks would get sent to |
171 | // another window because we said we weren't the preferred handler type. |
148 | // another window because we said we weren't the preferred handler type. |
172 | // I'm going to change the default now...if we can handle the content, |
149 | // I'm going to change the default now...if we can handle the content, |
173 | // and someone didn't EXPLICITLY set a nsIURIContentListener at the top |
150 | // and someone didn't EXPLICITLY set a nsIURIContentListener at the top |
174 | // of our docshell chain, then we'll now always attempt to process the |
151 | // of our docshell chain, then we'll now always attempt to process the |
175 | // content ourselves... |
152 | // content ourselves... |
176 | return CanHandleContent(aContentType, |
153 | return CanHandleContent(aContentType, |
177 | PR_TRUE, |
154 | PR_TRUE, |
178 | aDesiredContentType, |
155 | aDesiredContentType, |
179 | aCanHandle); |
156 | aCanHandle); |
180 | } |
157 | } |
181 | |
158 | |
182 | NS_IMETHODIMP |
159 | NS_IMETHODIMP |
183 | nsDSURIContentListener::CanHandleContent(const char* aContentType, |
160 | nsDSURIContentListener::CanHandleContent(const char* aContentType, |
184 | PRBool aIsContentPreferred, |
161 | PRBool aIsContentPreferred, |
185 | char ** aDesiredContentType, |
162 | char ** aDesiredContentType, |
186 | PRBool* aCanHandleContent) |
163 | PRBool* aCanHandleContent) |
187 | { |
164 | { |
188 | nsresult rv; |
165 | nsresult rv; |
189 | NS_ENSURE_ARG_POINTER(aCanHandleContent); |
166 | NS_ENSURE_ARG_POINTER(aCanHandleContent); |
190 | NS_ENSURE_ARG_POINTER(aDesiredContentType); |
167 | NS_ENSURE_ARG_POINTER(aDesiredContentType); |
191 | |
168 | |
192 | *aCanHandleContent = PR_FALSE; |
169 | *aCanHandleContent = PR_FALSE; |
193 | |
170 | |
194 | if (aContentType && mCatMgr) |
171 | if (aContentType && mCatMgr) |
195 | { |
172 | { |
196 | nsXPIDLCString value; |
173 | nsXPIDLCString value; |
197 | rv = mCatMgr->GetCategoryEntry("Gecko-Content-Viewers", |
174 | rv = mCatMgr->GetCategoryEntry("Gecko-Content-Viewers", |
198 | aContentType, |
175 | aContentType, |
199 | getter_Copies(value)); |
176 | getter_Copies(value)); |
200 | |
177 | |
201 | // If the category manager can't find what we're looking for |
178 | // If the category manager can't find what we're looking for |
202 | // it returns NS_ERROR_NOT_AVAILABLE, we don't want to propagate |
179 | // it returns NS_ERROR_NOT_AVAILABLE, we don't want to propagate |
203 | // that to the caller since it's really not a failure |
180 | // that to the caller since it's really not a failure |
204 | |
181 | |
205 | if (NS_FAILED(rv) && rv != NS_ERROR_NOT_AVAILABLE) |
182 | if (NS_FAILED(rv) && rv != NS_ERROR_NOT_AVAILABLE) |
206 | return rv; |
183 | return rv; |
207 | |
184 | |
208 | if (value && *value) |
185 | if (value && *value) |
209 | *aCanHandleContent = PR_TRUE; |
186 | *aCanHandleContent = PR_TRUE; |
210 | } |
187 | } |
211 | |
188 | |
212 | return NS_OK; |
189 | return NS_OK; |
213 | } |
190 | } |
214 | |
191 | |
215 | NS_IMETHODIMP |
192 | NS_IMETHODIMP |
216 | nsDSURIContentListener::GetLoadCookie(nsISupports ** aLoadCookie) |
193 | nsDSURIContentListener::GetLoadCookie(nsISupports ** aLoadCookie) |
217 | { |
194 | { |
218 | return mDocShell->GetLoadCookie(aLoadCookie); |
195 | return mDocShell->GetLoadCookie(aLoadCookie); |
219 | } |
196 | } |
220 | |
197 | |
221 | NS_IMETHODIMP |
198 | NS_IMETHODIMP |
222 | nsDSURIContentListener::SetLoadCookie(nsISupports * aLoadCookie) |
199 | nsDSURIContentListener::SetLoadCookie(nsISupports * aLoadCookie) |
223 | { |
200 | { |
224 | return mDocShell->SetLoadCookie(aLoadCookie); |
201 | return mDocShell->SetLoadCookie(aLoadCookie); |
225 | } |
202 | } |
226 | |
203 | |
227 | NS_IMETHODIMP |
204 | NS_IMETHODIMP |
228 | nsDSURIContentListener::GetParentContentListener(nsIURIContentListener** |
205 | nsDSURIContentListener::GetParentContentListener(nsIURIContentListener** |
229 | aParentListener) |
206 | aParentListener) |
230 | { |
207 | { |
231 | if (mWeakParentContentListener) |
208 | if (mWeakParentContentListener) |
232 | { |
209 | { |
233 | nsCOMPtr<nsIURIContentListener> tempListener = |
210 | nsCOMPtr<nsIURIContentListener> tempListener = |
234 | do_QueryReferent(mWeakParentContentListener); |
211 | do_QueryReferent(mWeakParentContentListener); |
235 | *aParentListener = tempListener; |
212 | *aParentListener = tempListener; |
236 | NS_IF_ADDREF(*aParentListener); |
213 | NS_IF_ADDREF(*aParentListener); |
237 | } |
214 | } |
238 | else { |
215 | else { |
239 | *aParentListener = mParentContentListener; |
216 | *aParentListener = mParentContentListener; |
240 | NS_IF_ADDREF(*aParentListener); |
217 | NS_IF_ADDREF(*aParentListener); |
241 | } |
218 | } |
242 | return NS_OK; |
219 | return NS_OK; |
243 | } |
220 | } |
244 | |
221 | |
245 | NS_IMETHODIMP |
222 | NS_IMETHODIMP |
246 | nsDSURIContentListener::SetParentContentListener(nsIURIContentListener* |
223 | nsDSURIContentListener::SetParentContentListener(nsIURIContentListener* |
247 | aParentListener) |
224 | aParentListener) |
248 | { |
225 | { |
249 | if (aParentListener) |
226 | if (aParentListener) |
250 | { |
227 | { |
251 | // Store the parent listener as a weak ref. Parents not supporting |
228 | // Store the parent listener as a weak ref. Parents not supporting |
252 | // nsISupportsWeakReference assert but may still be used. |
229 | // nsISupportsWeakReference assert but may still be used. |
253 | mParentContentListener = nsnull; |
230 | mParentContentListener = nsnull; |
254 | mWeakParentContentListener = do_GetWeakReference(aParentListener); |
231 | mWeakParentContentListener = do_GetWeakReference(aParentListener); |
255 | if (!mWeakParentContentListener) |
232 | if (!mWeakParentContentListener) |
256 | { |
233 | { |
257 | mParentContentListener = aParentListener; |
234 | mParentContentListener = aParentListener; |
258 | } |
235 | } |
259 | } |
236 | } |
260 | else |
237 | else |
261 | { |
238 | { |
262 | mWeakParentContentListener = nsnull; |
239 | mWeakParentContentListener = nsnull; |
263 | mParentContentListener = nsnull; |
240 | mParentContentListener = nsnull; |
264 | } |
241 | } |
265 | return NS_OK; |
242 | return NS_OK; |
266 | } |
243 | } |
267 | |
244 | |
268 | //***************************************************************************** |
245 | //***************************************************************************** |
269 | // nsDSURIContentListener: Helpers |
246 | // nsDSURIContentListener: Helpers |
270 | //***************************************************************************** |
247 | //***************************************************************************** |
271 | |
248 | |
272 | //***************************************************************************** |
249 | //***************************************************************************** |
273 | // nsDSURIContentListener: Accessors |
250 | // nsDSURIContentListener: Accessors |
274 | //***************************************************************************** |
251 | //***************************************************************************** |
275 | |
252 | |
276 | void nsDSURIContentListener::DocShell(nsDocShell* aDocShell) |
253 | void nsDSURIContentListener::DocShell(nsDocShell* aDocShell) |
277 | { |
254 | { |
278 | mDocShell = aDocShell; |
255 | mDocShell = aDocShell; |
279 | } |
256 | } |
280 | |
257 | |
281 | nsDocShell* nsDSURIContentListener::DocShell() |
258 | nsDocShell* nsDSURIContentListener::DocShell() |
282 | { |
259 | { |
283 | return mDocShell; |
260 | return mDocShell; |
284 | } |
261 | } |
285 | |
262 | |