1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=2 sw=2 et tw=80: */
3 /* ***** BEGIN LICENSE BLOCK *****
4 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
6 * The contents of this file are subject to the Mozilla Public License Version
7 * 1.1 (the "License"); you may not use this file except in compliance with
8 * the License. You may obtain a copy of the License at
9 * http://www.mozilla.org/MPL/
11 * Software distributed under the License is distributed on an "AS IS" basis,
12 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13 * for the specific language governing rights and limitations under the
16 * The Original Code is mozilla.org code.
18 * The Initial Developer of the Original Code is
19 * Netscape Communications Corporation.
20 * Portions created by the Initial Developer are Copyright (C) 1998
21 * the Initial Developer. All Rights Reserved.
24 * Travis Bogard <travis@netscape.com>
25 * Pierre Phaneuf <pp@ludusdesign.com>
27 * Alternatively, the contents of this file may be used under the terms of
28 * either of the GNU General Public License Version 2 or later (the "GPL"),
29 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
30 * in which case the provisions of the GPL or the LGPL are applicable instead
31 * of those above. If you wish to allow use of your version of this file only
32 * under the terms of either the GPL or the LGPL, and not to allow others to
33 * use your version of this file under the terms of the MPL, indicate your
34 * decision by deleting the provisions above and replace them with the notice
35 * and other provisions required by the GPL or the LGPL. If you do not delete
36 * the provisions above, a recipient may use your version of this file under
37 * the terms of any one of the MPL, the GPL or the LGPL.
39 * ***** END LICENSE BLOCK ***** */
41 #include "nsGlobalWindow.h"
42 #include "nsIScriptSecurityManager.h"
43 #include "nsIScriptContext.h"
44 #include "nsIDocShell.h"
45 #include "nsIDocShellLoadInfo.h"
46 #include "nsIWebNavigation.h"
47 #include "nsCDefaultURIFixup.h"
48 #include "nsIURIFixup.h"
50 #include "nsIJARURI.h"
51 #include "nsIIOService.h"
52 #include "nsIServiceManager.h"
53 #include "nsNetUtil.h"
59 #include "nsJSUtils.h"
60 #include "nsIDOMWindow.h"
61 #include "nsIDOMDocument.h"
62 #include "nsIDocument.h"
63 #include "nsIPresShell.h"
64 #include "nsPresContext.h"
65 #include "nsIJSContextStack.h"
66 #include "nsXPIDLString.h"
67 #include "nsDOMError.h"
68 #include "nsDOMClassInfo.h"
70 #include "nsIProtocolHandler.h"
71 #include "nsReadableUtils.h"
72 #include "nsITextToSubURI.h"
73 #include "nsContentUtils.h"
74 #include "nsJSUtils.h"
77 GetContextFromStack(nsIJSContextStack
*aStack
, JSContext
**aContext
)
79 nsCOMPtr
<nsIJSContextStackIterator
>
80 iterator(do_CreateInstance("@mozilla.org/js/xpc/ContextStackIterator;1"));
81 NS_ENSURE_TRUE(iterator
, NS_ERROR_FAILURE
);
83 nsresult rv
= iterator
->Reset(aStack
);
84 NS_ENSURE_SUCCESS(rv
, rv
);
87 while (NS_SUCCEEDED(iterator
->Done(&done
)) && !done
) {
88 rv
= iterator
->Prev(aContext
);
89 NS_ASSERTION(NS_SUCCEEDED(rv
), "Broken iterator implementation");
91 // Consider a null context the end of the line.
96 if (nsJSUtils::GetDynamicScriptContext(*aContext
)) {
107 GetDocumentCharacterSetForURI(const nsAString
& aHref
, nsACString
& aCharset
)
113 nsCOMPtr
<nsIJSContextStack
> stack(do_GetService("@mozilla.org/js/xpc/ContextStack;1", &rv
));
114 NS_ENSURE_SUCCESS(rv
, rv
);
118 rv
= GetContextFromStack(stack
, &cx
);
119 NS_ENSURE_SUCCESS(rv
, rv
);
122 nsCOMPtr
<nsIDOMWindow
> window
=
123 do_QueryInterface(nsJSUtils::GetDynamicScriptGlobal(cx
));
124 NS_ENSURE_TRUE(window
, NS_ERROR_FAILURE
);
126 nsCOMPtr
<nsIDOMDocument
> domDoc
;
127 rv
= window
->GetDocument(getter_AddRefs(domDoc
));
128 NS_ENSURE_SUCCESS(rv
, rv
);
130 nsCOMPtr
<nsIDocument
> doc(do_QueryInterface(domDoc
));
133 aCharset
= doc
->GetDocumentCharacterSet();
140 nsLocation::nsLocation(nsIDocShell
*aDocShell
)
142 mDocShell
= do_GetWeakReference(aDocShell
);
145 nsLocation::~nsLocation()
149 DOMCI_DATA(Location
, nsLocation
)
151 // QueryInterface implementation for nsLocation
152 NS_INTERFACE_MAP_BEGIN(nsLocation
)
153 NS_INTERFACE_MAP_ENTRY(nsIDOMLocation
)
154 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports
, nsIDOMLocation
)
155 NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(Location
)
159 NS_IMPL_ADDREF(nsLocation
)
160 NS_IMPL_RELEASE(nsLocation
)
163 nsLocation::SetDocShell(nsIDocShell
*aDocShell
)
165 mDocShell
= do_GetWeakReference(aDocShell
);
169 nsLocation::GetDocShell()
171 nsCOMPtr
<nsIDocShell
> docshell(do_QueryReferent(mDocShell
));
175 // Try to get the the document corresponding to the given JSStackFrame.
176 static already_AddRefed
<nsIDocument
>
177 GetFrameDocument(JSContext
*cx
, JSStackFrame
*fp
)
182 JSObject
* scope
= JS_GetFrameScopeChain(cx
, fp
);
186 JSAutoEnterCompartment ac
;
187 if (!ac
.enter(cx
, scope
))
190 nsCOMPtr
<nsIDOMWindow
> window
=
191 do_QueryInterface(nsJSUtils::GetStaticScriptGlobal(cx
, scope
));
195 // If it's a window, get its document.
196 nsCOMPtr
<nsIDOMDocument
> domDoc
;
197 window
->GetDocument(getter_AddRefs(domDoc
));
198 nsCOMPtr
<nsIDocument
> doc
= do_QueryInterface(domDoc
);
203 nsLocation::CheckURL(nsIURI
* aURI
, nsIDocShellLoadInfo
** aLoadInfo
)
207 nsCOMPtr
<nsIDocShell
> docShell(do_QueryReferent(mDocShell
));
208 NS_ENSURE_TRUE(docShell
, NS_ERROR_NOT_AVAILABLE
);
211 // Get JSContext from stack.
212 nsCOMPtr
<nsIJSContextStack
>
213 stack(do_GetService("@mozilla.org/js/xpc/ContextStack;1", &rv
));
214 NS_ENSURE_SUCCESS(rv
, rv
);
218 NS_ENSURE_SUCCESS(GetContextFromStack(stack
, &cx
), NS_ERROR_FAILURE
);
220 nsCOMPtr
<nsISupports
> owner
;
221 nsCOMPtr
<nsIURI
> sourceURI
;
224 // No cx means that there's no JS running, or at least no JS that
225 // was run through code that properly pushed a context onto the
226 // context stack (as all code that runs JS off of web pages
227 // does). We won't bother with security checks in this case, but
228 // we need to create the loadinfo etc.
230 // Get security manager.
231 nsCOMPtr
<nsIScriptSecurityManager
>
232 secMan(do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID
, &rv
));
233 NS_ENSURE_SUCCESS(rv
, rv
);
235 // Check to see if URI is allowed.
236 rv
= secMan
->CheckLoadURIFromScript(cx
, aURI
);
237 NS_ENSURE_SUCCESS(rv
, rv
);
239 // Now get the principal to use when loading the URI
240 // First, get the principal and frame.
242 nsIPrincipal
* principal
= secMan
->GetCxSubjectPrincipalAndFrame(cx
, &fp
);
243 NS_ENSURE_TRUE(principal
, NS_ERROR_FAILURE
);
245 nsCOMPtr
<nsIURI
> principalURI
;
246 principal
->GetURI(getter_AddRefs(principalURI
));
248 // Make the load's referrer reflect changes to the document's URI caused by
249 // push/replaceState, if possible. First, get the document corresponding to
250 // fp. If the document's original URI (i.e. its URI before
251 // push/replaceState) matches the principal's URI, use the document's
252 // current URI as the referrer. If they don't match, use the principal's
255 nsCOMPtr
<nsIDocument
> frameDoc
= GetFrameDocument(cx
, fp
);
256 nsCOMPtr
<nsIURI
> docOriginalURI
, docCurrentURI
;
258 docOriginalURI
= frameDoc
->GetOriginalURI();
259 docCurrentURI
= frameDoc
->GetDocumentURI();
262 PRBool urisEqual
= PR_FALSE
;
263 if (docOriginalURI
&& docCurrentURI
&& principalURI
) {
264 principalURI
->Equals(docOriginalURI
, &urisEqual
);
268 sourceURI
= docCurrentURI
;
271 sourceURI
= principalURI
;
274 owner
= do_QueryInterface(principal
);
278 nsCOMPtr
<nsIDocShellLoadInfo
> loadInfo
;
279 docShell
->CreateLoadInfo(getter_AddRefs(loadInfo
));
280 NS_ENSURE_TRUE(loadInfo
, NS_ERROR_FAILURE
);
282 loadInfo
->SetOwner(owner
);
285 loadInfo
->SetReferrer(sourceURI
);
288 loadInfo
.swap(*aLoadInfo
);
294 nsLocation::GetURI(nsIURI
** aURI
, PRBool aGetInnermostURI
)
299 nsCOMPtr
<nsIDocShell
> docShell(do_QueryReferent(mDocShell
));
300 nsCOMPtr
<nsIWebNavigation
> webNav(do_QueryInterface(docShell
, &rv
));
305 nsCOMPtr
<nsIURI
> uri
;
306 rv
= webNav
->GetCurrentURI(getter_AddRefs(uri
));
307 NS_ENSURE_SUCCESS(rv
, rv
);
309 // It is valid for docshell to return a null URI. Don't try to fixup
315 if (aGetInnermostURI
) {
316 nsCOMPtr
<nsIJARURI
> jarURI(do_QueryInterface(uri
));
318 jarURI
->GetJARFile(getter_AddRefs(uri
));
319 jarURI
= do_QueryInterface(uri
);
323 NS_ASSERTION(uri
, "nsJARURI screwed up?");
325 nsCOMPtr
<nsIURIFixup
> urifixup(do_GetService(NS_URIFIXUP_CONTRACTID
, &rv
));
326 NS_ENSURE_SUCCESS(rv
, rv
);
328 return urifixup
->CreateExposableURI(uri
, aURI
);
332 nsLocation::GetWritableURI(nsIURI
** aURI
)
336 nsCOMPtr
<nsIURI
> uri
;
338 nsresult rv
= GetURI(getter_AddRefs(uri
));
339 if (NS_FAILED(rv
) || !uri
) {
343 return uri
->Clone(aURI
);
347 nsLocation::SetURI(nsIURI
* aURI
, PRBool aReplace
)
349 nsCOMPtr
<nsIDocShell
> docShell(do_QueryReferent(mDocShell
));
351 nsCOMPtr
<nsIDocShellLoadInfo
> loadInfo
;
352 nsCOMPtr
<nsIWebNavigation
> webNav(do_QueryInterface(docShell
));
354 if(NS_FAILED(CheckURL(aURI
, getter_AddRefs(loadInfo
))))
355 return NS_ERROR_FAILURE
;
358 loadInfo
->SetLoadType(nsIDocShellLoadInfo::loadStopContentAndReplace
);
360 loadInfo
->SetLoadType(nsIDocShellLoadInfo::loadStopContent
);
363 return docShell
->LoadURI(aURI
, loadInfo
,
364 nsIWebNavigation::LOAD_FLAGS_NONE
, PR_TRUE
);
371 nsLocation::GetHash(nsAString
& aHash
)
375 nsCOMPtr
<nsIURI
> uri
;
376 nsresult rv
= GetURI(getter_AddRefs(uri
));
378 nsCOMPtr
<nsIURL
> url(do_QueryInterface(uri
));
382 nsAutoString unicodeRef
;
384 rv
= url
->GetRef(ref
);
385 if (NS_SUCCEEDED(rv
)) {
386 nsCOMPtr
<nsITextToSubURI
> textToSubURI(
387 do_GetService(NS_ITEXTTOSUBURI_CONTRACTID
, &rv
));
389 if (NS_SUCCEEDED(rv
)) {
390 nsCAutoString charset
;
391 url
->GetOriginCharset(charset
);
393 rv
= textToSubURI
->UnEscapeURIForUI(charset
, ref
, unicodeRef
);
397 // Oh, well. No intl here!
399 CopyASCIItoUTF16(ref
, unicodeRef
);
404 if (NS_SUCCEEDED(rv
) && !unicodeRef
.IsEmpty()) {
405 aHash
.Assign(PRUnichar('#'));
406 aHash
.Append(unicodeRef
);
414 nsLocation::SetHash(const nsAString
& aHash
)
416 nsCOMPtr
<nsIURI
> uri
;
417 nsresult rv
= GetWritableURI(getter_AddRefs(uri
));
419 nsCOMPtr
<nsIURL
> url(do_QueryInterface(uri
));
421 NS_ConvertUTF16toUTF8
hash(aHash
);
422 if (hash
.IsEmpty() || hash
.First() != PRUnichar('#')) {
423 hash
.Insert(PRUnichar('#'), 0);
425 rv
= url
->SetRef(hash
);
426 if (NS_SUCCEEDED(rv
)) {
435 nsLocation::GetHost(nsAString
& aHost
)
439 nsCOMPtr
<nsIURI
> uri
;
442 result
= GetURI(getter_AddRefs(uri
), PR_TRUE
);
445 nsCAutoString hostport
;
447 result
= uri
->GetHostPort(hostport
);
449 if (NS_SUCCEEDED(result
)) {
450 AppendUTF8toUTF16(hostport
, aHost
);
458 nsLocation::SetHost(const nsAString
& aHost
)
460 nsCOMPtr
<nsIURI
> uri
;
461 nsresult rv
= GetWritableURI(getter_AddRefs(uri
));
464 rv
= uri
->SetHostPort(NS_ConvertUTF16toUTF8(aHost
));
465 if (NS_SUCCEEDED(rv
)) {
474 nsLocation::GetHostname(nsAString
& aHostname
)
476 aHostname
.Truncate();
478 nsCOMPtr
<nsIURI
> uri
;
481 result
= GetURI(getter_AddRefs(uri
), PR_TRUE
);
486 result
= uri
->GetHost(host
);
488 if (NS_SUCCEEDED(result
)) {
489 AppendUTF8toUTF16(host
, aHostname
);
497 nsLocation::SetHostname(const nsAString
& aHostname
)
499 nsCOMPtr
<nsIURI
> uri
;
500 nsresult rv
= GetWritableURI(getter_AddRefs(uri
));
503 rv
= uri
->SetHost(NS_ConvertUTF16toUTF8(aHostname
));
504 if (NS_SUCCEEDED(rv
)) {
513 nsLocation::GetHref(nsAString
& aHref
)
517 nsCOMPtr
<nsIURI
> uri
;
520 result
= GetURI(getter_AddRefs(uri
));
523 nsCAutoString uriString
;
525 result
= uri
->GetSpec(uriString
);
527 if (NS_SUCCEEDED(result
)) {
528 AppendUTF8toUTF16(uriString
, aHref
);
536 nsLocation::SetHref(const nsAString
& aHref
)
538 nsAutoString oldHref
;
541 // Get JSContext from stack.
542 nsCOMPtr
<nsIJSContextStack
>
543 stack(do_GetService("@mozilla.org/js/xpc/ContextStack;1", &rv
));
546 return NS_ERROR_FAILURE
;
550 if (NS_FAILED(GetContextFromStack(stack
, &cx
)))
551 return NS_ERROR_FAILURE
;
554 rv
= SetHrefWithContext(cx
, aHref
, PR_FALSE
);
556 rv
= GetHref(oldHref
);
558 if (NS_SUCCEEDED(rv
)) {
559 nsCOMPtr
<nsIURI
> oldUri
;
561 rv
= NS_NewURI(getter_AddRefs(oldUri
), oldHref
);
564 rv
= SetHrefWithBase(aHref
, oldUri
, PR_FALSE
);
573 nsLocation::SetHrefWithContext(JSContext
* cx
, const nsAString
& aHref
,
576 nsCOMPtr
<nsIURI
> base
;
578 // Get the source of the caller
579 nsresult result
= GetSourceBaseURL(cx
, getter_AddRefs(base
));
581 if (NS_FAILED(result
)) {
585 return SetHrefWithBase(aHref
, base
, aReplace
);
589 nsLocation::SetHrefWithBase(const nsAString
& aHref
, nsIURI
* aBase
,
593 nsCOMPtr
<nsIURI
> newUri
;
595 nsCOMPtr
<nsIDocShell
> docShell(do_QueryReferent(mDocShell
));
597 nsCAutoString docCharset
;
598 if (NS_SUCCEEDED(GetDocumentCharacterSetForURI(aHref
, docCharset
)))
599 result
= NS_NewURI(getter_AddRefs(newUri
), aHref
, docCharset
.get(), aBase
);
601 result
= NS_NewURI(getter_AddRefs(newUri
), aHref
, nsnull
, aBase
);
604 /* Check with the scriptContext if it is currently processing a script tag.
605 * If so, this must be a <script> tag with a location.href in it.
606 * we want to do a replace load, in such a situation.
607 * In other cases, for example if a event handler or a JS timer
608 * had a location.href in it, we want to do a normal load,
609 * so that the new url will be appended to Session History.
610 * This solution is tricky. Hopefully it isn't going to bite
611 * anywhere else. This is part of solution for bug # 39938, 72197
614 PRBool inScriptTag
=PR_FALSE
;
615 // Get JSContext from stack.
616 nsCOMPtr
<nsIJSContextStack
> stack(do_GetService("@mozilla.org/js/xpc/ContextStack;1", &result
));
621 result
= GetContextFromStack(stack
, &cx
);
623 nsIScriptContext
*scriptContext
=
624 nsJSUtils::GetDynamicScriptContext(cx
);
627 if (scriptContext
->GetProcessingScriptTag()) {
628 // Now check to make sure that the script is running in our window,
629 // since we only want to replace if the location is set by a
630 // <script> tag in the same window. See bug 178729.
631 nsCOMPtr
<nsIScriptGlobalObject
> ourGlobal(do_GetInterface(docShell
));
632 inScriptTag
= (ourGlobal
== scriptContext
->GetGlobalObject());
638 return SetURI(newUri
, aReplace
|| inScriptTag
);
645 nsLocation::GetPathname(nsAString
& aPathname
)
647 aPathname
.Truncate();
649 nsCOMPtr
<nsIURI
> uri
;
650 nsresult result
= NS_OK
;
652 result
= GetURI(getter_AddRefs(uri
));
654 nsCOMPtr
<nsIURL
> url(do_QueryInterface(uri
));
658 result
= url
->GetFilePath(file
);
660 if (NS_SUCCEEDED(result
)) {
661 AppendUTF8toUTF16(file
, aPathname
);
669 nsLocation::SetPathname(const nsAString
& aPathname
)
671 nsCOMPtr
<nsIURI
> uri
;
672 nsresult rv
= GetWritableURI(getter_AddRefs(uri
));
675 rv
= uri
->SetPath(NS_ConvertUTF16toUTF8(aPathname
));
676 if (NS_SUCCEEDED(rv
)) {
685 nsLocation::GetPort(nsAString
& aPort
)
689 nsCOMPtr
<nsIURI
> uri
;
690 nsresult result
= NS_OK
;
692 result
= GetURI(getter_AddRefs(uri
), PR_TRUE
);
696 result
= uri
->GetPort(&port
);
698 if (NS_SUCCEEDED(result
) && -1 != port
) {
699 nsAutoString portStr
;
700 portStr
.AppendInt(port
);
701 aPort
.Append(portStr
);
704 // Don't propagate this exception to caller
712 nsLocation::SetPort(const nsAString
& aPort
)
714 nsCOMPtr
<nsIURI
> uri
;
715 nsresult rv
= GetWritableURI(getter_AddRefs(uri
));
718 // perhaps use nsReadingIterators at some point?
719 NS_ConvertUTF16toUTF8
portStr(aPort
);
720 const char *buf
= portStr
.get();
732 rv
= uri
->SetPort(port
);
733 if (NS_SUCCEEDED(rv
)) {
742 nsLocation::GetProtocol(nsAString
& aProtocol
)
744 aProtocol
.SetLength(0);
746 nsCOMPtr
<nsIURI
> uri
;
747 nsresult result
= NS_OK
;
749 result
= GetURI(getter_AddRefs(uri
));
752 nsCAutoString protocol
;
754 result
= uri
->GetScheme(protocol
);
756 if (NS_SUCCEEDED(result
)) {
757 CopyASCIItoUTF16(protocol
, aProtocol
);
758 aProtocol
.Append(PRUnichar(':'));
766 nsLocation::SetProtocol(const nsAString
& aProtocol
)
768 nsCOMPtr
<nsIURI
> uri
;
769 nsresult rv
= GetWritableURI(getter_AddRefs(uri
));
772 rv
= uri
->SetScheme(NS_ConvertUTF16toUTF8(aProtocol
));
773 if (NS_SUCCEEDED(rv
)) {
782 nsLocation::GetSearch(nsAString
& aSearch
)
784 aSearch
.SetLength(0);
786 nsCOMPtr
<nsIURI
> uri
;
787 nsresult result
= NS_OK
;
789 result
= GetURI(getter_AddRefs(uri
));
791 nsCOMPtr
<nsIURL
> url(do_QueryInterface(uri
));
794 nsCAutoString search
;
796 result
= url
->GetQuery(search
);
798 if (NS_SUCCEEDED(result
) && !search
.IsEmpty()) {
799 aSearch
.Assign(PRUnichar('?'));
800 AppendUTF8toUTF16(search
, aSearch
);
808 nsLocation::SetSearch(const nsAString
& aSearch
)
810 nsCOMPtr
<nsIURI
> uri
;
811 nsresult rv
= GetWritableURI(getter_AddRefs(uri
));
813 nsCOMPtr
<nsIURL
> url(do_QueryInterface(uri
));
815 rv
= url
->SetQuery(NS_ConvertUTF16toUTF8(aSearch
));
816 if (NS_SUCCEEDED(rv
)) {
825 nsLocation::Reload(PRBool aForceget
)
828 nsCOMPtr
<nsIDocShell
> docShell(do_QueryReferent(mDocShell
));
829 nsCOMPtr
<nsIWebNavigation
> webNav(do_QueryInterface(docShell
));
830 nsCOMPtr
<nsPIDOMWindow
> window(do_GetInterface(docShell
));
832 if (window
&& window
->IsHandlingResizeEvent()) {
833 // location.reload() was called on a window that is handling a
834 // resize event. Sites do this since Netscape 4.x needed it, but
835 // we don't, and it's a horrible experience for nothing. In stead
836 // of reloading the page, just clear style data and reflow the
837 // page since some sites may use this trick to work around gecko
838 // reflow bugs, and this should have the same effect.
840 nsCOMPtr
<nsIDocument
> doc(do_QueryInterface(window
->GetExtantDocument()));
844 if (doc
&& (shell
= doc
->GetShell()) && (pcx
= shell
->GetPresContext())) {
845 pcx
->RebuildAllStyleData(NS_STYLE_HINT_REFLOW
);
852 PRUint32 reloadFlags
= nsIWebNavigation::LOAD_FLAGS_NONE
;
855 reloadFlags
= nsIWebNavigation::LOAD_FLAGS_BYPASS_CACHE
|
856 nsIWebNavigation::LOAD_FLAGS_BYPASS_PROXY
;
858 rv
= webNav
->Reload(reloadFlags
);
859 if (rv
== NS_BINDING_ABORTED
) {
860 // This happens when we attempt to reload a POST result and the user says
861 // no at the "do you want to reload?" prompt. Don't propagate this one
866 rv
= NS_ERROR_FAILURE
;
873 nsLocation::Replace(const nsAString
& aUrl
)
877 // Get JSContext from stack.
878 nsCOMPtr
<nsIJSContextStack
>
879 stack(do_GetService("@mozilla.org/js/xpc/ContextStack;1"));
884 rv
= GetContextFromStack(stack
, &cx
);
885 NS_ENSURE_SUCCESS(rv
, rv
);
887 return SetHrefWithContext(cx
, aUrl
, PR_TRUE
);
891 nsAutoString oldHref
;
893 rv
= GetHref(oldHref
);
894 NS_ENSURE_SUCCESS(rv
, rv
);
896 nsCOMPtr
<nsIURI
> oldUri
;
898 rv
= NS_NewURI(getter_AddRefs(oldUri
), oldHref
);
899 NS_ENSURE_SUCCESS(rv
, rv
);
901 return SetHrefWithBase(aUrl
, oldUri
, PR_TRUE
);
905 nsLocation::Assign(const nsAString
& aUrl
)
907 nsAutoString oldHref
;
908 nsresult result
= NS_OK
;
910 result
= GetHref(oldHref
);
912 if (NS_SUCCEEDED(result
)) {
913 nsCOMPtr
<nsIURI
> oldUri
;
915 result
= NS_NewURI(getter_AddRefs(oldUri
), oldHref
);
918 result
= SetHrefWithBase(aUrl
, oldUri
, PR_FALSE
);
926 nsLocation::ToString(nsAString
& aReturn
)
928 return GetHref(aReturn
);
932 nsLocation::GetSourceDocument(JSContext
* cx
, nsIDocument
** aDocument
)
934 // XXX Code duplicated from nsHTMLDocument
935 // XXX Tom said this reminded him of the "Six Degrees of
936 // Kevin Bacon" game. We try to get from here to there using
937 // whatever connections possible. The problem is that this
938 // could break if any of the connections along the way change.
939 // I wish there were a better way.
941 nsresult rv
= NS_ERROR_FAILURE
;
943 // We need to use the dynamically scoped global and assume that the
944 // current JSContext is a DOM context with a nsIScriptGlobalObject so
945 // that we can get the url of the caller.
946 // XXX This will fail on non-DOM contexts :(
948 nsCOMPtr
<nsIDOMWindow
> window
=
949 do_QueryInterface(nsJSUtils::GetDynamicScriptGlobal(cx
), &rv
);
952 nsCOMPtr
<nsIDOMDocument
> domDoc
;
953 rv
= window
->GetDocument(getter_AddRefs(domDoc
));
955 return CallQueryInterface(domDoc
, aDocument
);
965 nsLocation::GetSourceBaseURL(JSContext
* cx
, nsIURI
** sourceURL
)
967 nsCOMPtr
<nsIDocument
> doc
;
968 nsresult rv
= GetSourceDocument(cx
, getter_AddRefs(doc
));
970 *sourceURL
= doc
->GetBaseURI().get();