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

Reply via email to