| 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 | |