| |
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
| |
2 /* This Source Code Form is subject to the terms of the Mozilla Public |
| |
3 * License, v. 2.0. If a copy of the MPL was not distributed with this |
| |
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
| |
5 |
| |
6 #include "nsDocShell.h" |
| |
7 #include "nsDSURIContentListener.h" |
| |
8 #include "nsIChannel.h" |
| |
9 #include "nsServiceManagerUtils.h" |
| |
10 #include "nsDocShellCID.h" |
| |
11 #include "nsIWebNavigationInfo.h" |
| |
12 #include "nsIDocument.h" |
| |
13 #include "nsIDOMWindow.h" |
| |
14 #include "nsNetUtil.h" |
| |
15 #include "nsAutoPtr.h" |
| |
16 #include "nsIHttpChannel.h" |
| |
17 #include "nsIScriptSecurityManager.h" |
| |
18 #include "nsError.h" |
| |
19 #include "nsCharSeparatedTokenizer.h" |
| |
20 #include "nsIConsoleService.h" |
| |
21 #include "nsIScriptError.h" |
| |
22 #include "nsDocShellLoadTypes.h" |
| |
23 |
| |
24 using namespace mozilla; |
| |
25 |
| |
26 //***************************************************************************** |
| |
27 //*** nsDSURIContentListener: Object Management |
| |
28 //***************************************************************************** |
| |
29 |
| |
30 nsDSURIContentListener::nsDSURIContentListener(nsDocShell* aDocShell) |
| |
31 : mDocShell(aDocShell), |
| |
32 mParentContentListener(nullptr) |
| |
33 { |
| |
34 } |
| |
35 |
| |
36 nsDSURIContentListener::~nsDSURIContentListener() |
| |
37 { |
| |
38 } |
| |
39 |
| |
40 nsresult |
| |
41 nsDSURIContentListener::Init() |
| |
42 { |
| |
43 nsresult rv; |
| |
44 mNavInfo = do_GetService(NS_WEBNAVIGATION_INFO_CONTRACTID, &rv); |
| |
45 NS_ASSERTION(NS_SUCCEEDED(rv), "Failed to get webnav info"); |
| |
46 return rv; |
| |
47 } |
| |
48 |
| |
49 |
| |
50 //***************************************************************************** |
| |
51 // nsDSURIContentListener::nsISupports |
| |
52 //***************************************************************************** |
| |
53 |
| |
54 NS_IMPL_ADDREF(nsDSURIContentListener) |
| |
55 NS_IMPL_RELEASE(nsDSURIContentListener) |
| |
56 |
| |
57 NS_INTERFACE_MAP_BEGIN(nsDSURIContentListener) |
| |
58 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIURIContentListener) |
| |
59 NS_INTERFACE_MAP_ENTRY(nsIURIContentListener) |
| |
60 NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference) |
| |
61 NS_INTERFACE_MAP_END |
| |
62 |
| |
63 //***************************************************************************** |
| |
64 // nsDSURIContentListener::nsIURIContentListener |
| |
65 //***************************************************************************** |
| |
66 |
| |
67 NS_IMETHODIMP |
| |
68 nsDSURIContentListener::OnStartURIOpen(nsIURI* aURI, bool* aAbortOpen) |
| |
69 { |
| |
70 // If mDocShell is null here, that means someone's starting a load |
| |
71 // in our docshell after it's already been destroyed. Don't let |
| |
72 // that happen. |
| |
73 if (!mDocShell) { |
| |
74 *aAbortOpen = true; |
| |
75 return NS_OK; |
| |
76 } |
| |
77 |
| |
78 nsCOMPtr<nsIURIContentListener> parentListener; |
| |
79 GetParentContentListener(getter_AddRefs(parentListener)); |
| |
80 if (parentListener) |
| |
81 return parentListener->OnStartURIOpen(aURI, aAbortOpen); |
| |
82 |
| |
83 return NS_OK; |
| |
84 } |
| |
85 |
| |
86 NS_IMETHODIMP |
| |
87 nsDSURIContentListener::DoContent(const char* aContentType, |
| |
88 bool aIsContentPreferred, |
| |
89 nsIRequest* request, |
| |
90 nsIStreamListener** aContentHandler, |
| |
91 bool* aAbortProcess) |
| |
92 { |
| |
93 nsresult rv; |
| |
94 NS_ENSURE_ARG_POINTER(aContentHandler); |
| |
95 NS_ENSURE_TRUE(mDocShell, NS_ERROR_FAILURE); |
| |
96 |
| |
97 // Check whether X-Frame-Options permits us to load this content in an |
| |
98 // iframe and abort the load (unless we've disabled x-frame-options |
| |
99 // checking). |
| |
100 if (!CheckFrameOptions(request)) { |
| |
101 *aAbortProcess = true; |
| |
102 return NS_OK; |
| |
103 } |
| |
104 |
| |
105 *aAbortProcess = false; |
| |
106 |
| |
107 // determine if the channel has just been retargeted to us... |
| |
108 nsLoadFlags loadFlags = 0; |
| |
109 nsCOMPtr<nsIChannel> aOpenedChannel = do_QueryInterface(request); |
| |
110 |
| |
111 if (aOpenedChannel) |
| |
112 aOpenedChannel->GetLoadFlags(&loadFlags); |
| |
113 |
| |
114 if(loadFlags & nsIChannel::LOAD_RETARGETED_DOCUMENT_URI) |
| |
115 { |
| |
116 // XXX: Why does this not stop the content too? |
| |
117 mDocShell->Stop(nsIWebNavigation::STOP_NETWORK); |
| |
118 |
| |
119 mDocShell->SetLoadType(aIsContentPreferred ? LOAD_LINK : LOAD_NORMAL); |
| |
120 } |
| |
121 |
| |
122 rv = mDocShell->CreateContentViewer(aContentType, request, aContentHandler); |
| |
123 |
| |
124 if (rv == NS_ERROR_REMOTE_XUL) { |
| |
125 request->Cancel(rv); |
| |
126 *aAbortProcess = true; |
| |
127 return NS_OK; |
| |
128 } |
| |
129 |
| |
130 if (NS_FAILED(rv)) { |
| |
131 // we don't know how to handle the content |
| |
132 *aContentHandler = nullptr; |
| |
133 return rv; |
| |
134 } |
| |
135 |
| |
136 if (loadFlags & nsIChannel::LOAD_RETARGETED_DOCUMENT_URI) { |
| |
137 nsCOMPtr<nsIDOMWindow> domWindow = do_GetInterface(static_cast<nsIDocShell*>(mDocShell)); |
| |
138 NS_ENSURE_TRUE(domWindow, NS_ERROR_FAILURE); |
| |
139 domWindow->Focus(); |
| |
140 } |
| |
141 |
| |
142 return NS_OK; |
| |
143 } |
| |
144 |
| |
145 NS_IMETHODIMP |
| |
146 nsDSURIContentListener::IsPreferred(const char* aContentType, |
| |
147 char ** aDesiredContentType, |
| |
148 bool* aCanHandle) |
| |
149 { |
| |
150 NS_ENSURE_ARG_POINTER(aCanHandle); |
| |
151 NS_ENSURE_ARG_POINTER(aDesiredContentType); |
| |
152 |
| |
153 // the docshell has no idea if it is the preferred content provider or not. |
| |
154 // It needs to ask its parent if it is the preferred content handler or not... |
| |
155 |
| |
156 nsCOMPtr<nsIURIContentListener> parentListener; |
| |
157 GetParentContentListener(getter_AddRefs(parentListener)); |
| |
158 if (parentListener) { |
| |
159 return parentListener->IsPreferred(aContentType, |
| |
160 aDesiredContentType, |
| |
161 aCanHandle); |
| |
162 } |
| |
163 // we used to return false here if we didn't have a parent properly |
| |
164 // registered at the top of the docshell hierarchy to dictate what |
| |
165 // content types this docshell should be a preferred handler for. But |
| |
166 // this really makes it hard for developers using iframe or browser tags |
| |
167 // because then they need to make sure they implement |
| |
168 // nsIURIContentListener otherwise all link clicks would get sent to |
| |
169 // another window because we said we weren't the preferred handler type. |
| |
170 // I'm going to change the default now...if we can handle the content, |
| |
171 // and someone didn't EXPLICITLY set a nsIURIContentListener at the top |
| |
172 // of our docshell chain, then we'll now always attempt to process the |
| |
173 // content ourselves... |
| |
174 return CanHandleContent(aContentType, |
| |
175 true, |
| |
176 aDesiredContentType, |
| |
177 aCanHandle); |
| |
178 } |
| |
179 |
| |
180 NS_IMETHODIMP |
| |
181 nsDSURIContentListener::CanHandleContent(const char* aContentType, |
| |
182 bool aIsContentPreferred, |
| |
183 char ** aDesiredContentType, |
| |
184 bool* aCanHandleContent) |
| |
185 { |
| |
186 NS_PRECONDITION(aCanHandleContent, "Null out param?"); |
| |
187 NS_ENSURE_ARG_POINTER(aDesiredContentType); |
| |
188 |
| |
189 *aCanHandleContent = false; |
| |
190 *aDesiredContentType = nullptr; |
| |
191 |
| |
192 nsresult rv = NS_OK; |
| |
193 if (aContentType) { |
| |
194 uint32_t canHandle = nsIWebNavigationInfo::UNSUPPORTED; |
| |
195 rv = mNavInfo->IsTypeSupported(nsDependentCString(aContentType), |
| |
196 mDocShell, |
| |
197 &canHandle); |
| |
198 *aCanHandleContent = (canHandle != nsIWebNavigationInfo::UNSUPPORTED); |
| |
199 } |
| |
200 |
| |
201 return rv; |
| |
202 } |
| |
203 |
| |
204 NS_IMETHODIMP |
| |
205 nsDSURIContentListener::GetLoadCookie(nsISupports ** aLoadCookie) |
| |
206 { |
| |
207 NS_IF_ADDREF(*aLoadCookie = nsDocShell::GetAsSupports(mDocShell)); |
| |
208 return NS_OK; |
| |
209 } |
| |
210 |
| |
211 NS_IMETHODIMP |
| |
212 nsDSURIContentListener::SetLoadCookie(nsISupports * aLoadCookie) |
| |
213 { |
| |
214 #ifdef DEBUG |
| |
215 nsRefPtr<nsDocLoader> cookieAsDocLoader = |
| |
216 nsDocLoader::GetAsDocLoader(aLoadCookie); |
| |
217 NS_ASSERTION(cookieAsDocLoader && cookieAsDocLoader == mDocShell, |
| |
218 "Invalid load cookie being set!"); |
| |
219 #endif |
| |
220 return NS_OK; |
| |
221 } |
| |
222 |
| |
223 NS_IMETHODIMP |
| |
224 nsDSURIContentListener::GetParentContentListener(nsIURIContentListener** |
| |
225 aParentListener) |
| |
226 { |
| |
227 if (mWeakParentContentListener) |
| |
228 { |
| |
229 nsCOMPtr<nsIURIContentListener> tempListener = |
| |
230 do_QueryReferent(mWeakParentContentListener); |
| |
231 *aParentListener = tempListener; |
| |
232 NS_IF_ADDREF(*aParentListener); |
| |
233 } |
| |
234 else { |
| |
235 *aParentListener = mParentContentListener; |
| |
236 NS_IF_ADDREF(*aParentListener); |
| |
237 } |
| |
238 return NS_OK; |
| |
239 } |
| |
240 |
| |
241 NS_IMETHODIMP |
| |
242 nsDSURIContentListener::SetParentContentListener(nsIURIContentListener* |
| |
243 aParentListener) |
| |
244 { |
| |
245 if (aParentListener) |
| |
246 { |
| |
247 // Store the parent listener as a weak ref. Parents not supporting |
| |
248 // nsISupportsWeakReference assert but may still be used. |
| |
249 mParentContentListener = nullptr; |
| |
250 mWeakParentContentListener = do_GetWeakReference(aParentListener); |
| |
251 if (!mWeakParentContentListener) |
| |
252 { |
| |
253 mParentContentListener = aParentListener; |
| |
254 } |
| |
255 } |
| |
256 else |
| |
257 { |
| |
258 mWeakParentContentListener = nullptr; |
| |
259 mParentContentListener = nullptr; |
| |
260 } |
| |
261 return NS_OK; |
| |
262 } |
| |
263 |
| |
264 bool nsDSURIContentListener::CheckOneFrameOptionsPolicy(nsIHttpChannel *httpChannel, |
| |
265 const nsAString& policy) { |
| |
266 static const char allowFrom[] = "allow-from"; |
| |
267 const uint32_t allowFromLen = ArrayLength(allowFrom) - 1; |
| |
268 bool isAllowFrom = |
| |
269 StringHead(policy, allowFromLen).LowerCaseEqualsLiteral(allowFrom); |
| |
270 |
| |
271 // return early if header does not have one of the values with meaning |
| |
272 if (!policy.LowerCaseEqualsLiteral("deny") && |
| |
273 !policy.LowerCaseEqualsLiteral("sameorigin") && |
| |
274 !isAllowFrom) |
| |
275 return true; |
| |
276 |
| |
277 nsCOMPtr<nsIURI> uri; |
| |
278 httpChannel->GetURI(getter_AddRefs(uri)); |
| |
279 |
| |
280 // XXXkhuey when does this happen? Is returning true safe here? |
| |
281 if (!mDocShell) { |
| |
282 return true; |
| |
283 } |
| |
284 |
| |
285 // We need to check the location of this window and the location of the top |
| |
286 // window, if we're not the top. X-F-O: SAMEORIGIN requires that the |
| |
287 // document must be same-origin with top window. X-F-O: DENY requires that |
| |
288 // the document must never be framed. |
| |
289 nsCOMPtr<nsIDOMWindow> thisWindow = do_GetInterface(static_cast<nsIDocShell*>(mDocShell)); |
| |
290 // If we don't have DOMWindow there is no risk of clickjacking |
| |
291 if (!thisWindow) |
| |
292 return true; |
| |
293 |
| |
294 // GetScriptableTop, not GetTop, because we want this to respect |
| |
295 // <iframe mozbrowser> boundaries. |
| |
296 nsCOMPtr<nsIDOMWindow> topWindow; |
| |
297 thisWindow->GetScriptableTop(getter_AddRefs(topWindow)); |
| |
298 |
| |
299 // if the document is in the top window, it's not in a frame. |
| |
300 if (thisWindow == topWindow) |
| |
301 return true; |
| |
302 |
| |
303 // Find the top docshell in our parent chain that doesn't have the system |
| |
304 // principal and use it for the principal comparison. Finding the top |
| |
305 // content-type docshell doesn't work because some chrome documents are |
| |
306 // loaded in content docshells (see bug 593387). |
| |
307 nsCOMPtr<nsIDocShellTreeItem> thisDocShellItem(do_QueryInterface( |
| |
308 static_cast<nsIDocShell*> (mDocShell))); |
| |
309 nsCOMPtr<nsIDocShellTreeItem> parentDocShellItem, |
| |
310 curDocShellItem = thisDocShellItem; |
| |
311 nsCOMPtr<nsIDocument> topDoc; |
| |
312 nsresult rv; |
| |
313 nsCOMPtr<nsIScriptSecurityManager> ssm = |
| |
314 do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv); |
| |
315 if (!ssm) { |
| |
316 MOZ_CRASH(); |
| |
317 } |
| |
318 |
| |
319 // Traverse up the parent chain and stop when we see a docshell whose |
| |
320 // parent has a system principal, or a docshell corresponding to |
| |
321 // <iframe mozbrowser>. |
| |
322 while (NS_SUCCEEDED(curDocShellItem->GetParent(getter_AddRefs(parentDocShellItem))) && |
| |
323 parentDocShellItem) { |
| |
324 |
| |
325 nsCOMPtr<nsIDocShell> curDocShell = do_QueryInterface(curDocShellItem); |
| |
326 if (curDocShell && curDocShell->GetIsBrowserOrApp()) { |
| |
327 break; |
| |
328 } |
| |
329 |
| |
330 bool system = false; |
| |
331 topDoc = do_GetInterface(parentDocShellItem); |
| |
332 if (topDoc) { |
| |
333 if (NS_SUCCEEDED(ssm->IsSystemPrincipal(topDoc->NodePrincipal(), |
| |
334 &system)) && system) { |
| |
335 // Found a system-principled doc: last docshell was top. |
| |
336 break; |
| |
337 } |
| |
338 } |
| |
339 else { |
| |
340 return false; |
| |
341 } |
| |
342 curDocShellItem = parentDocShellItem; |
| |
343 } |
| |
344 |
| |
345 // If this document has the top non-SystemPrincipal docshell it is not being |
| |
346 // framed or it is being framed by a chrome document, which we allow. |
| |
347 if (curDocShellItem == thisDocShellItem) |
| |
348 return true; |
| |
349 |
| |
350 // If the value of the header is DENY, and the previous condition is |
| |
351 // not met (current docshell is not the top docshell), prohibit the |
| |
352 // load. |
| |
353 if (policy.LowerCaseEqualsLiteral("deny")) { |
| |
354 ReportXFOViolation(curDocShellItem, uri, eDENY); |
| |
355 return false; |
| |
356 } |
| |
357 |
| |
358 topDoc = do_GetInterface(curDocShellItem); |
| |
359 nsCOMPtr<nsIURI> topUri; |
| |
360 topDoc->NodePrincipal()->GetURI(getter_AddRefs(topUri)); |
| |
361 |
| |
362 // If the X-Frame-Options value is SAMEORIGIN, then the top frame in the |
| |
363 // parent chain must be from the same origin as this document. |
| |
364 if (policy.LowerCaseEqualsLiteral("sameorigin")) { |
| |
365 rv = ssm->CheckSameOriginURI(uri, topUri, true); |
| |
366 if (NS_FAILED(rv)) { |
| |
367 ReportXFOViolation(curDocShellItem, uri, eSAMEORIGIN); |
| |
368 return false; /* wasn't same-origin */ |
| |
369 } |
| |
370 } |
| |
371 |
| |
372 // If the X-Frame-Options value is "allow-from [uri]", then the top |
| |
373 // frame in the parent chain must be from that origin |
| |
374 if (isAllowFrom) { |
| |
375 if (policy.Length() == allowFromLen || |
| |
376 (policy[allowFromLen] != ' ' && |
| |
377 policy[allowFromLen] != '\t')) { |
| |
378 ReportXFOViolation(curDocShellItem, uri, eALLOWFROM); |
| |
379 return false; |
| |
380 } |
| |
381 rv = NS_NewURI(getter_AddRefs(uri), |
| |
382 Substring(policy, allowFromLen)); |
| |
383 if (NS_FAILED(rv)) |
| |
384 return false; |
| |
385 |
| |
386 rv = ssm->CheckSameOriginURI(uri, topUri, true); |
| |
387 if (NS_FAILED(rv)) { |
| |
388 ReportXFOViolation(curDocShellItem, uri, eALLOWFROM); |
| |
389 return false; |
| |
390 } |
| |
391 } |
| |
392 |
| |
393 return true; |
| |
394 } |
| |
395 |
| |
396 // Check if X-Frame-Options permits this document to be loaded as a subdocument. |
| |
397 // This will iterate through and check any number of X-Frame-Options policies |
| |
398 // in the request (comma-separated in a header, multiple headers, etc). |
| |
399 bool nsDSURIContentListener::CheckFrameOptions(nsIRequest *request) |
| |
400 { |
| |
401 nsresult rv; |
| |
402 nsCOMPtr<nsIChannel> chan = do_QueryInterface(request); |
| |
403 if (!chan) { |
| |
404 return true; |
| |
405 } |
| |
406 |
| |
407 nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(chan); |
| |
408 if (!httpChannel) { |
| |
409 // check if it is hiding in a multipart channel |
| |
410 rv = mDocShell->GetHttpChannel(chan, getter_AddRefs(httpChannel)); |
| |
411 if (NS_FAILED(rv)) |
| |
412 return false; |
| |
413 } |
| |
414 |
| |
415 if (!httpChannel) { |
| |
416 return true; |
| |
417 } |
| |
418 |
| |
419 nsAutoCString xfoHeaderCValue; |
| |
420 httpChannel->GetResponseHeader(NS_LITERAL_CSTRING("X-Frame-Options"), |
| |
421 xfoHeaderCValue); |
| |
422 NS_ConvertUTF8toUTF16 xfoHeaderValue(xfoHeaderCValue); |
| |
423 |
| |
424 // if no header value, there's nothing to do. |
| |
425 if (xfoHeaderValue.IsEmpty()) |
| |
426 return true; |
| |
427 |
| |
428 // iterate through all the header values (usually there's only one, but can |
| |
429 // be many. If any want to deny the load, deny the load. |
| |
430 nsCharSeparatedTokenizer tokenizer(xfoHeaderValue, ','); |
| |
431 while (tokenizer.hasMoreTokens()) { |
| |
432 const nsSubstring& tok = tokenizer.nextToken(); |
| |
433 if (!CheckOneFrameOptionsPolicy(httpChannel, tok)) { |
| |
434 // cancel the load and display about:blank |
| |
435 httpChannel->Cancel(NS_BINDING_ABORTED); |
| |
436 if (mDocShell) { |
| |
437 nsCOMPtr<nsIWebNavigation> webNav(do_QueryObject(mDocShell)); |
| |
438 if (webNav) { |
| |
439 webNav->LoadURI(MOZ_UTF16("about:blank"), |
| |
440 0, nullptr, nullptr, nullptr); |
| |
441 } |
| |
442 } |
| |
443 return false; |
| |
444 } |
| |
445 } |
| |
446 |
| |
447 return true; |
| |
448 } |
| |
449 |
| |
450 void |
| |
451 nsDSURIContentListener::ReportXFOViolation(nsIDocShellTreeItem* aTopDocShellItem, |
| |
452 nsIURI* aThisURI, |
| |
453 XFOHeader aHeader) |
| |
454 { |
| |
455 nsresult rv = NS_OK; |
| |
456 |
| |
457 nsCOMPtr<nsPIDOMWindow> topOuterWindow = do_GetInterface(aTopDocShellItem); |
| |
458 if (!topOuterWindow) |
| |
459 return; |
| |
460 |
| |
461 NS_ASSERTION(topOuterWindow->IsOuterWindow(), "Huh?"); |
| |
462 nsPIDOMWindow* topInnerWindow = topOuterWindow->GetCurrentInnerWindow(); |
| |
463 if (!topInnerWindow) |
| |
464 return; |
| |
465 |
| |
466 nsCOMPtr<nsIURI> topURI; |
| |
467 |
| |
468 nsCOMPtr<nsIDocument> document; |
| |
469 |
| |
470 document = do_GetInterface(aTopDocShellItem); |
| |
471 rv = document->NodePrincipal()->GetURI(getter_AddRefs(topURI)); |
| |
472 if (NS_FAILED(rv)) |
| |
473 return; |
| |
474 |
| |
475 if (!topURI) |
| |
476 return; |
| |
477 |
| |
478 nsCString topURIString; |
| |
479 nsCString thisURIString; |
| |
480 |
| |
481 rv = topURI->GetSpec(topURIString); |
| |
482 if (NS_FAILED(rv)) |
| |
483 return; |
| |
484 |
| |
485 rv = aThisURI->GetSpec(thisURIString); |
| |
486 if (NS_FAILED(rv)) |
| |
487 return; |
| |
488 |
| |
489 nsCOMPtr<nsIConsoleService> consoleService = |
| |
490 do_GetService(NS_CONSOLESERVICE_CONTRACTID); |
| |
491 nsCOMPtr<nsIScriptError> errorObject = |
| |
492 do_CreateInstance(NS_SCRIPTERROR_CONTRACTID); |
| |
493 |
| |
494 if (!consoleService || !errorObject) |
| |
495 return; |
| |
496 |
| |
497 nsString msg = NS_LITERAL_STRING("Load denied by X-Frame-Options: "); |
| |
498 msg.Append(NS_ConvertUTF8toUTF16(thisURIString)); |
| |
499 |
| |
500 switch (aHeader) { |
| |
501 case eDENY: |
| |
502 msg.AppendLiteral(" does not permit framing."); |
| |
503 break; |
| |
504 case eSAMEORIGIN: |
| |
505 msg.AppendLiteral(" does not permit cross-origin framing."); |
| |
506 break; |
| |
507 case eALLOWFROM: |
| |
508 msg.AppendLiteral(" does not permit framing by "); |
| |
509 msg.Append(NS_ConvertUTF8toUTF16(topURIString)); |
| |
510 msg.AppendLiteral("."); |
| |
511 break; |
| |
512 } |
| |
513 |
| |
514 rv = errorObject->InitWithWindowID(msg, EmptyString(), EmptyString(), 0, 0, |
| |
515 nsIScriptError::errorFlag, |
| |
516 "X-Frame-Options", |
| |
517 topInnerWindow->WindowID()); |
| |
518 if (NS_FAILED(rv)) |
| |
519 return; |
| |
520 |
| |
521 consoleService->LogMessage(errorObject); |
| |
522 } |