diff --git a/dom/interfaces/threads/nsIDOMWorkers.idl b/dom/interfaces/threads/nsIDOMWorkers.idl index d6c743d85372..4b636808d37e 100644 --- a/dom/interfaces/threads/nsIDOMWorkers.idl +++ b/dom/interfaces/threads/nsIDOMWorkers.idl @@ -83,6 +83,21 @@ interface nsIWorkerErrorEvent : nsIDOMEvent in unsigned long aLinenoArg); }; +[scriptable, uuid(17a005c3-4f2f-4bb6-b169-c181fa6873de)] +interface nsIWorkerLocation : nsISupports +{ + readonly attribute AUTF8String href; + readonly attribute AUTF8String protocol; + readonly attribute AUTF8String host; + readonly attribute AUTF8String hostname; + readonly attribute AUTF8String port; + readonly attribute AUTF8String pathname; + readonly attribute AUTF8String search; + readonly attribute AUTF8String hash; + + AUTF8String toString(); +}; + [scriptable, uuid(74fb665a-e477-4ce2-b3c6-c58b1b28b6c3)] interface nsIWorkerNavigator : nsISupports { @@ -92,11 +107,12 @@ interface nsIWorkerNavigator : nsISupports readonly attribute DOMString userAgent; }; -[scriptable, uuid(d7d7cf59-6c8a-4598-8753-630953ae7409)] +[scriptable, uuid(c111e7d3-8044-4458-aa7b-637696ffb841)] interface nsIWorkerGlobalScope : nsISupports { readonly attribute nsIWorkerGlobalScope self; readonly attribute nsIWorkerNavigator navigator; + readonly attribute nsIWorkerLocation location; attribute nsIDOMEventListener onerror; }; diff --git a/dom/src/threads/Makefile.in b/dom/src/threads/Makefile.in index aa620c58f344..06e18d4a5ee1 100644 --- a/dom/src/threads/Makefile.in +++ b/dom/src/threads/Makefile.in @@ -71,6 +71,7 @@ CPPSRCS = \ nsDOMThreadService.cpp \ nsDOMWorker.cpp \ nsDOMWorkerEvents.cpp \ + nsDOMWorkerLocation.cpp \ nsDOMWorkerMessageHandler.cpp \ nsDOMWorkerNavigator.cpp \ nsDOMWorkerPool.cpp \ diff --git a/dom/src/threads/nsDOMWorker.cpp b/dom/src/threads/nsDOMWorker.cpp index 4c919c206ab6..b05338b02b40 100644 --- a/dom/src/threads/nsDOMWorker.cpp +++ b/dom/src/threads/nsDOMWorker.cpp @@ -58,6 +58,7 @@ #include "nsDOMThreadService.h" #include "nsDOMWorkerEvents.h" +#include "nsDOMWorkerLocation.h" #include "nsDOMWorkerNavigator.h" #include "nsDOMWorkerPool.h" #include "nsDOMWorkerScriptLoader.h" @@ -698,6 +699,18 @@ nsDOMWorkerScope::GetNavigator(nsIWorkerNavigator** _retval) return NS_OK; } +NS_IMETHODIMP +nsDOMWorkerScope::GetLocation(nsIWorkerLocation** _retval) +{ + NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!"); + + nsCOMPtr location = mWorker->GetLocation(); + NS_ASSERTION(location, "This should never be null!"); + + location.forget(_retval); + return NS_OK; +} + NS_IMETHODIMP nsDOMWorkerScope::GetOnerror(nsIDOMEventListener** aOnerror) { @@ -1744,6 +1757,24 @@ nsDOMWorker::ResumeFeatures() } } +nsresult +nsDOMWorker::SetURI(nsIURI* aURI) +{ + NS_ASSERTION(aURI, "Don't hand me a null pointer!"); + NS_ASSERTION(!mURI && !mLocation, "Called more than once?!"); + NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); + + mURI = aURI; + + nsCOMPtr url(do_QueryInterface(aURI)); + NS_ENSURE_TRUE(url, NS_ERROR_NO_INTERFACE); + + mLocation = nsDOMWorkerLocation::NewLocation(url); + NS_ENSURE_TRUE(mLocation, NS_ERROR_FAILURE); + + return NS_OK; +} + nsresult nsDOMWorker::FireCloseRunnable(PRIntervalTime aTimeoutInterval, PRBool aClearQueue, diff --git a/dom/src/threads/nsDOMWorker.h b/dom/src/threads/nsDOMWorker.h index 56942e4e499c..9b648ef47d4e 100644 --- a/dom/src/threads/nsDOMWorker.h +++ b/dom/src/threads/nsDOMWorker.h @@ -266,9 +266,7 @@ private: return mURI; } - void SetURI(nsIURI* aURI) { - mURI = aURI; - } + nsresult SetURI(nsIURI* aURI); nsresult FireCloseRunnable(PRIntervalTime aTimeoutInterval, PRBool aClearQueue, @@ -277,6 +275,10 @@ private: nsresult TerminateInternal(PRBool aFromFinalize); + nsIWorkerLocation* GetLocation() { + return mLocation; + } + private: // mParent will live as long as mParentWN but only mParentWN will keep the JS @@ -314,6 +316,8 @@ private: nsCOMPtr mKillTimer; + nsCOMPtr mLocation; + PRPackedBool mSuspended; PRPackedBool mCompileAttempted; }; diff --git a/dom/src/threads/nsDOMWorkerLocation.cpp b/dom/src/threads/nsDOMWorkerLocation.cpp new file mode 100644 index 000000000000..776ab9176c39 --- /dev/null +++ b/dom/src/threads/nsDOMWorkerLocation.cpp @@ -0,0 +1,223 @@ +/* -*- Mode: c++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is worker threads. + * + * The Initial Developer of the Original Code is + * Mozilla Corporation. + * Portions created by the Initial Developer are Copyright (C) 2009 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Ben Turner (Original Author) + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "nsDOMWorkerLocation.h" + +#include "nsIClassInfoImpl.h" +#include "nsITextToSubURI.h" +#include "nsIURL.h" + +#include "nsDOMWorkerMacros.h" + +#include "nsAutoPtr.h" +#include "nsEscape.h" +#include "nsNetUtil.h" + +#define XPC_MAP_CLASSNAME nsDOMWorkerLocation +#define XPC_MAP_QUOTED_CLASSNAME "WorkerLocation" + +#define XPC_MAP_FLAGS \ + nsIXPCScriptable::USE_JSSTUB_FOR_ADDPROPERTY | \ + nsIXPCScriptable::USE_JSSTUB_FOR_DELPROPERTY | \ + nsIXPCScriptable::USE_JSSTUB_FOR_SETPROPERTY | \ + nsIXPCScriptable::DONT_ENUM_QUERY_INTERFACE | \ + nsIXPCScriptable::CLASSINFO_INTERFACES_ONLY | \ + nsIXPCScriptable::DONT_REFLECT_INTERFACE_NAMES + +#include "xpc_map_end.h" + +NS_IMPL_THREADSAFE_ISUPPORTS3(nsDOMWorkerLocation, nsIWorkerLocation, + nsIClassInfo, + nsIXPCScriptable) + +NS_IMPL_CI_INTERFACE_GETTER1(nsDOMWorkerLocation, nsIWorkerLocation) + +NS_IMPL_THREADSAFE_DOM_CI_GETINTERFACES(nsDOMWorkerLocation) +NS_IMPL_THREADSAFE_DOM_CI_ALL_THE_REST(nsDOMWorkerLocation) + +NS_IMETHODIMP +nsDOMWorkerLocation::GetHelperForLanguage(PRUint32 aLanguage, + nsISupports** _retval) +{ + if (aLanguage == nsIProgrammingLanguage::JAVASCRIPT) { + NS_ADDREF(*_retval = NS_ISUPPORTS_CAST(nsIWorkerLocation*, this)); + } + else { + *_retval = nsnull; + } + return NS_OK; +} + +// static +already_AddRefed +nsDOMWorkerLocation::NewLocation(nsIURL* aURL) +{ + NS_ASSERTION(aURL, "Don't hand me a null pointer!"); + + nsAutoPtr location(new nsDOMWorkerLocation()); + NS_ENSURE_TRUE(location, nsnull); + + nsresult rv = aURL->GetSpec(location->mHref); + NS_ENSURE_SUCCESS(rv, nsnull); + + rv = aURL->GetHost(location->mHostname); + NS_ENSURE_SUCCESS(rv, nsnull); + + rv = aURL->GetPath(location->mPathname); + NS_ENSURE_SUCCESS(rv, nsnull); + + nsCString temp; + + rv = aURL->GetQuery(temp); + NS_ENSURE_SUCCESS(rv, nsnull); + if (!temp.IsEmpty()) { + location->mSearch.AssignLiteral("?"); + location->mSearch.Append(temp); + } + + rv = aURL->GetRef(temp); + NS_ENSURE_SUCCESS(rv, nsnull); + + if (!temp.IsEmpty()) { + nsAutoString unicodeRef; + + nsCOMPtr converter = + do_GetService(NS_ITEXTTOSUBURI_CONTRACTID, &rv); + if (NS_SUCCEEDED(rv)) { + nsCString charset; + rv = aURL->GetOriginCharset(charset); + if (NS_SUCCEEDED(rv)) { + rv = converter->UnEscapeURIForUI(charset, temp, unicodeRef); + if (NS_SUCCEEDED(rv)) { + location->mHash.AssignLiteral("#"); + location->mHash.Append(NS_ConvertUTF16toUTF8(unicodeRef)); + } + } + } + + if (NS_FAILED(rv)) { + location->mHash.AssignLiteral("#"); + location->mHash.Append(temp); + } + } + + rv = aURL->GetScheme(location->mProtocol); + NS_ENSURE_SUCCESS(rv, nsnull); + + location->mProtocol.AppendLiteral(":"); + + PRInt32 port; + rv = aURL->GetPort(&port); + if (NS_SUCCEEDED(rv) && port != -1) { + location->mPort.AppendInt(port); + + nsCAutoString host(location->mHostname); + host.AppendLiteral(":"); + host.Append(location->mPort); + + location->mHost.Assign(host); + } + else { + location->mHost.Assign(location->mHostname); + } + + NS_ADDREF(location); + return location.forget(); +} + +NS_IMETHODIMP +nsDOMWorkerLocation::GetHref(nsACString& aHref) +{ + aHref.Assign(mHref); + return NS_OK; +} + +NS_IMETHODIMP +nsDOMWorkerLocation::GetProtocol(nsACString& aProtocol) +{ + aProtocol.Assign(mProtocol); + return NS_OK; +} + +NS_IMETHODIMP +nsDOMWorkerLocation::GetHost(nsACString& aHost) +{ + aHost.Assign(mHost); + return NS_OK; +} + +NS_IMETHODIMP +nsDOMWorkerLocation::GetHostname(nsACString& aHostname) +{ + aHostname.Assign(mHostname); + return NS_OK; +} + +NS_IMETHODIMP +nsDOMWorkerLocation::GetPort(nsACString& aPort) +{ + aPort.Assign(mPort); + return NS_OK; +} + +NS_IMETHODIMP +nsDOMWorkerLocation::GetPathname(nsACString& aPathname) +{ + aPathname.Assign(mPathname); + return NS_OK; +} + +NS_IMETHODIMP +nsDOMWorkerLocation::GetSearch(nsACString& aSearch) +{ + aSearch.Assign(mSearch); + return NS_OK; +} + +NS_IMETHODIMP +nsDOMWorkerLocation::GetHash(nsACString& aHash) +{ + aHash.Assign(mHash); + return NS_OK; +} + +NS_IMETHODIMP +nsDOMWorkerLocation::ToString(nsACString& _retval) +{ + return GetHref(_retval); +} diff --git a/dom/src/threads/nsDOMWorkerLocation.h b/dom/src/threads/nsDOMWorkerLocation.h new file mode 100644 index 000000000000..e3832d20811b --- /dev/null +++ b/dom/src/threads/nsDOMWorkerLocation.h @@ -0,0 +1,77 @@ +/* -*- Mode: c++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is worker threads. + * + * The Initial Developer of the Original Code is + * Mozilla Corporation. + * Portions created by the Initial Developer are Copyright (C) 2009 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Ben Turner (Original Author) + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef __NSDOMWORKERLOCATION_H__ +#define __NSDOMWORKERLOCATION_H__ + +#include "nsIClassInfo.h" +#include "nsIDOMWorkers.h" +#include "nsIXPCScriptable.h" + +#include "nsCOMPtr.h" +#include "nsStringGlue.h" + +class nsIURL; + +class nsDOMWorkerLocation : public nsIWorkerLocation, + public nsIClassInfo, + public nsIXPCScriptable +{ +public: + NS_DECL_ISUPPORTS + NS_DECL_NSIWORKERLOCATION + NS_DECL_NSICLASSINFO + NS_DECL_NSIXPCSCRIPTABLE + + static already_AddRefed NewLocation(nsIURL* aURL); + +protected: + nsDOMWorkerLocation() { } + +private: + nsCString mHref; + nsCString mProtocol; + nsCString mHost; + nsCString mHostname; + nsCString mPort; + nsCString mPathname; + nsCString mSearch; + nsCString mHash; +}; + +#endif /* __NSDOMWORKERLOCATION_H__ */ diff --git a/dom/src/threads/nsDOMWorkerScriptLoader.cpp b/dom/src/threads/nsDOMWorkerScriptLoader.cpp index 6acda1c7c22c..5651a4bcd1ec 100644 --- a/dom/src/threads/nsDOMWorkerScriptLoader.cpp +++ b/dom/src/threads/nsDOMWorkerScriptLoader.cpp @@ -483,7 +483,9 @@ nsDOMWorkerScriptLoader::RunInternal() // Set the principal and URI on the new worker. mWorker->SetPrincipal(principal); - mWorker->SetURI(uri); + + rv = mWorker->SetURI(uri); + NS_ENSURE_SUCCESS(rv, rv); } else { rv = secMan->CheckLoadURIWithPrincipal(principal, uri, 0); diff --git a/dom/src/threads/test/Makefile.in b/dom/src/threads/test/Makefile.in index 1ffd60ecd6c1..4771fac12540 100644 --- a/dom/src/threads/test/Makefile.in +++ b/dom/src/threads/test/Makefile.in @@ -66,6 +66,8 @@ _TEST_FILES = \ importScripts_worker_imported4.js \ test_json.html \ json_worker.js \ + test_location.html \ + location_worker.js \ test_longThread.html \ longThread_worker.js \ test_navigator.html \ diff --git a/dom/src/threads/test/location_worker.js b/dom/src/threads/test/location_worker.js new file mode 100644 index 000000000000..a6b90e5f56ed --- /dev/null +++ b/dom/src/threads/test/location_worker.js @@ -0,0 +1,4 @@ +for (var string in self.location) { + postMessage({ "string": string, "value": self.location[string] }); +} +postMessage({"string": "testfinished", "value": self.location.toString()}); diff --git a/dom/src/threads/test/test_location.html b/dom/src/threads/test/test_location.html new file mode 100644 index 000000000000..6524deed14e1 --- /dev/null +++ b/dom/src/threads/test/test_location.html @@ -0,0 +1,64 @@ + + + + + Test for DOM Worker Location + + + + + +

+ +
+
+
+ +