Revision: 6541 Author: j...@google.com Date: Thu Oct 29 08:49:04 2009 Log: Update XPCOM plugin to compute the top window and URL itself rather than rely on the values passed in from the JS code.
http://code.google.com/p/google-web-toolkit/source/detail?r=6541 Modified: /changes/jat/single-xpi/plugins/xpcom/ExternalWrapper.cpp /changes/jat/single-xpi/plugins/xpcom/ExternalWrapper.h ======================================= --- /changes/jat/single-xpi/plugins/xpcom/ExternalWrapper.cpp Thu Sep 3 15:22:56 2009 +++ /changes/jat/single-xpi/plugins/xpcom/ExternalWrapper.cpp Thu Oct 29 08:49:04 2009 @@ -23,6 +23,15 @@ #include "nsMemory.h" #include "nsServiceManagerUtils.h" #include "nsIPromptService.h" +#include "nsIDOMWindow.h" +#include "nsIDOMWindowInternal.h" +#include "nsIDOMLocation.h" +#include "nsXPCOMStrings.h" +#include "nsICategoryManager.h" +#include "nsIJSContextStack.h" +#include "nsIScriptContext.h" +#include "nsIScriptGlobalObject.h" +#include "nsPIDOMWindow.h" #ifndef NS_IMPL_ISUPPORTS2_CI #include "nsIClassInfoImpl.h" // 1.9 only @@ -68,19 +77,148 @@ userAgent.assign(userAgentStr.get()); return NS_OK; } + +/** + * Get JS window object. + * + * @param win output parameter to store the window object + * @return true on success + */ +static bool getWindowObject(nsIDOMWindow** win) { + // Get JSContext from stack. + nsCOMPtr<nsIJSContextStack> stack = + do_GetService("@mozilla.org/js/xpc/ContextStack;1"); + if (!stack) { + Debug::log(Debug::Error) << "getWindowObject: no context stack" + << Debug::flush; + return false; + } + JSContext *cx; + if (NS_FAILED(stack->Peek(&cx)) || !cx) { + Debug::log(Debug::Error) << "getWindowObject: no context on stack" + << Debug::flush; + return false; + } + if (!(::JS_GetOptions(cx) & JSOPTION_PRIVATE_IS_NSISUPPORTS)) { + Debug::log(Debug::Error) + << "getWindowObject: context doesn't have nsISupports" << Debug::flush; + return false; + } + + nsCOMPtr<nsIScriptContext> scx = + do_QueryInterface(static_cast<nsISupports *> + (::JS_GetContextPrivate(cx))); + if (!scx) { + Debug::log(Debug::Error) << "getWindowObject: no script context" + << Debug::flush; + return false; + } + nsCOMPtr<nsIScriptGlobalObject> globalObj = scx->GetGlobalObject(); + if (!globalObj) { + Debug::log(Debug::Error) << "getWindowObject: no global object" + << Debug::flush; + return false; + } + nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(globalObj); + if (!window) { + Debug::log(Debug::Error) << "getWindowObject: window is null" + << Debug::flush; + return false; + } + NS_ADDREF(*win = window); + return true; +} + +/** + * Get the URL of a window. + * + * @param win DOMWindowInternal instance + * @param url output wide string for the URL + * @return true if successful + */ +static bool getWindowUrl(nsIDOMWindowInternal* win, nsAString& url) { + nsCOMPtr<nsIDOMLocation> loc; + if (win->GetLocation(getter_AddRefs(loc)) != NS_OK) { + Debug::log(Debug::Info) << "Unable to get location" << Debug::flush; + return false; + } + if (loc->GetHref(url) != NS_OK) { + Debug::log(Debug::Info) << "Unable to get URL" << Debug::flush; + return false; + } + return true; +} + +/** + * Get the top-level window for a given window, and its URL. + * + * @param win window to start from + * @param topWinRet output parameter to store top window + * @param topUrl output parameter to store URL + * @return true on success, false on error (already logged) + */ +static bool getTopWindow(nsIDOMWindow* win, nsIDOMWindowInternal** topWinRet, + nsAString& topUrl) { + nsCOMPtr<nsIDOMWindow> topWin; + if (win->GetTop(getter_AddRefs(topWin)) != NS_OK) { + Debug::log(Debug::Error) << "Unable to get top window" << Debug::flush; + return false; + } + nsresult rv; + nsCOMPtr<nsIDOMWindowInternal> topWinInt = do_QueryInterface(topWin, &rv); + if (rv != NS_OK) { + Debug::log(Debug::Error) << "Unable to QI DOMWindowInternal" + << Debug::flush; + return false; + } + nsCOMPtr<nsIDOMWindowInternal> opener; + if (topWinInt->GetOpener(getter_AddRefs(opener)) != NS_OK) { + Debug::log(Debug::Debugging) << "Unable to get opener" << Debug::flush; + *topWinRet = topWinInt; + return true; + } + if (!getWindowUrl(topWinInt, topUrl)) { + Debug::log(Debug::Error) << "Unable to get url of top window" + << Debug::flush; + return false; + } + while (opener) { + nsCOMPtr<nsIDOMWindow> nextTopWin; + if (opener->GetTop(getter_AddRefs(nextTopWin)) != NS_OK) { + Debug::log(Debug::Debugging) << "Unable to get next top" << Debug::flush; + break; + } + nsCOMPtr<nsIDOMWindowInternal> nextTopWinInt = do_QueryInterface( + nextTopWin, &rv); + if (rv != NS_OK) { + Debug::log(Debug::Warning) << "Unable to QI DOMWindowInternal on next" + << Debug::flush; + break; + } + if (!getWindowUrl(nextTopWinInt, topUrl)) { + break; + } + Debug::log(Debug::Debugging) << " current url: " << topUrl << Debug::flush; + topWin = nextTopWin; + topWinInt = nextTopWinInt; + if (topWinInt->GetOpener(getter_AddRefs(opener)) != NS_OK) { + break; + } + } + Debug::log(Debug::Info) << " Top url: " << topUrl << Debug::flush; + *topWinRet = topWinInt; + return true; +} std::string ExternalWrapper::computeTabIdentity() { std::string returnVal; if (!windowWatcher) { return returnVal; } - nsCOMPtr<nsIDOMWindow> topWindow(domWindow); - if (topWindow->GetTop(getter_AddRefs(topWindow)) != NS_OK) { - Debug::log(Debug::Warning) << "Unable to get top window" << Debug::flush; - return returnVal; - } + nsCOMPtr<nsPIDOMWindow> innerWin = do_QueryInterface(topWindow); + nsCOMPtr<nsPIDOMWindow> outerWin = innerWin->GetOuterWindow(); nsCOMPtr<nsIWebBrowserChrome> chrome; - if (windowWatcher->GetChromeForWindow(topWindow.get(), + if (windowWatcher->GetChromeForWindow(outerWin.get(), getter_AddRefs(chrome)) != NS_OK) { Debug::log(Debug::Warning) << "Unable to get browser chrome for window" << Debug::flush; @@ -92,11 +230,26 @@ return returnVal; } -NS_IMETHODIMP ExternalWrapper::Init(nsIDOMWindow* domWindow, +// TODO(jat): remove suppliedWindow and update hosted.html API +NS_IMETHODIMP ExternalWrapper::Init(nsIDOMWindow* suppliedWindow, PRBool *_retval) { - Debug::log(Debug::Spam) << "Init" << Debug::flush; - this->domWindow = domWindow; - *_retval = true; + Debug::log(Debug::Debugging) << "Plugin initialized from hosted.html" + << Debug::flush; + *_retval = false; + nsCOMPtr<nsIDOMWindow> computedWindow; + if (getWindowObject(getter_AddRefs(computedWindow))) { + Debug::log(Debug::Debugging) << " passed window=" << suppliedWindow + << ", computed=" << computedWindow << Debug::flush; + domWindow = computedWindow; + } else { + Debug::log(Debug::Warning) << " using supplied window object" + << Debug::flush; + // TODO(jat): remove this + domWindow = suppliedWindow; + } + if (getTopWindow(domWindow, getter_AddRefs(topWindow), url)) { + *_retval = true; + } return NS_OK; } @@ -123,16 +276,18 @@ return include; } -NS_IMETHODIMP ExternalWrapper::Connect(const nsACString& url, +// TODO(jat): remove suppliedUrl and update hosted.html API +NS_IMETHODIMP ExternalWrapper::Connect(const nsACString& suppliedUrl, const nsACString& sessionKey, const nsACString& aAddr, const nsACString& aModuleName, const nsACString& hostedHtmlVersion, PRBool *_retval) { - Debug::log(Debug::Spam) << "Connect(url=" << url << ", sessionKey=" + Debug::log(Debug::Info) << "Connect(url=" << url << ", sessionKey=" << sessionKey << ", address=" << aAddr << ", module=" << aModuleName << ", hostedHtmlVersion=" << hostedHtmlVersion << Debug::flush; // TODO: string utilities? - nsCString urlAutoStr(url); + nsCString urlAutoStr; + NS_UTF16ToCString(url, NS_CSTRING_ENCODING_UTF8, urlAutoStr); nsCString sessionKeyAutoStr(sessionKey); nsCString addrAutoStr(aAddr); nsCString moduleAutoStr(aModuleName); @@ -173,8 +328,7 @@ std::string hostedHtmlVersionStr(hostedHtmlVersionAutoStr.get()); if (!channel->init(sessionHandler.get(), BROWSERCHANNEL_PROTOCOL_VERSION, - BROWSERCHANNEL_PROTOCOL_VERSION, - hostedHtmlVersionStr)) { + BROWSERCHANNEL_PROTOCOL_VERSION, hostedHtmlVersionStr)) { *_retval = false; return NS_OK; } @@ -211,13 +365,16 @@ return strcmp(ascii, utf8.get()) == 0; } -NS_IMETHODIMP ExternalWrapper::CanCreateWrapper(const nsIID * iid, char **_retval) { - Debug::log(Debug::Spam) << "ExternalWrapper::CanCreateWrapper" << Debug::flush; +NS_IMETHODIMP ExternalWrapper::CanCreateWrapper(const nsIID * iid, + char **_retval) { + Debug::log(Debug::Spam) << "ExternalWrapper::CanCreateWrapper" + << Debug::flush; *_retval = cloneAllAccess(); return NS_OK; } -NS_IMETHODIMP ExternalWrapper::CanCallMethod(const nsIID * iid, const PRUnichar *methodName, char **_retval) { +NS_IMETHODIMP ExternalWrapper::CanCallMethod(const nsIID * iid, + const PRUnichar *methodName, char **_retval) { Debug::log(Debug::Spam) << "ExternalWrapper::CanCallMethod" << Debug::flush; if (strEquals(methodName, "connect") || strEquals(methodName, "init")) { *_retval = cloneAllAccess(); @@ -227,12 +384,14 @@ return NS_OK; } -NS_IMETHODIMP ExternalWrapper::CanGetProperty(const nsIID * iid, const PRUnichar *propertyName, char **_retval) { +NS_IMETHODIMP ExternalWrapper::CanGetProperty(const nsIID * iid, + const PRUnichar *propertyName, char **_retval) { Debug::log(Debug::Spam) << "ExternalWrapper::CanGetProperty" << Debug::flush; *_retval = nsnull; return NS_OK; } -NS_IMETHODIMP ExternalWrapper::CanSetProperty(const nsIID * iid, const PRUnichar *propertyName, char **_retval) { +NS_IMETHODIMP ExternalWrapper::CanSetProperty(const nsIID * iid, + const PRUnichar *propertyName, char **_retval) { Debug::log(Debug::Spam) << "ExternalWrapper::CanSetProperty" << Debug::flush; *_retval = nsnull; return NS_OK; ======================================= --- /changes/jat/single-xpi/plugins/xpcom/ExternalWrapper.h Thu Sep 3 15:22:56 2009 +++ /changes/jat/single-xpi/plugins/xpcom/ExternalWrapper.h Thu Oct 29 08:49:04 2009 @@ -54,6 +54,8 @@ private: nsCOMPtr<nsIDOMWindow> domWindow; + nsCOMPtr<nsIDOMWindowInternal> topWindow; + nsString url; nsCOMPtr<Preferences> preferences; scoped_ptr<FFSessionHandler> sessionHandler; nsCOMPtr<nsIWindowWatcher> windowWatcher; @@ -74,10 +76,18 @@ }; -inline Debug::DebugStream& operator<<(Debug::DebugStream& dbg, const nsACString& str) { +inline Debug::DebugStream& operator<<(Debug::DebugStream& dbg, + const nsACString& str) { nsCString copy(str); dbg << copy.get(); return dbg; } + +inline Debug::DebugStream& operator<<(Debug::DebugStream& dbg, + const nsAString& str) { + NS_ConvertUTF16toUTF8 copy(str); + dbg << copy.get(); + return dbg; +} #endif --~--~---------~--~----~------------~-------~--~----~ http://groups.google.com/group/Google-Web-Toolkit-Contributors -~----------~----~----~----~------~----~------~--~---