Bug 793547 - Query the underlying data object if it exists for uri handed to the Win8 CEH in ShellExecute operations. Fixes some clipped url issues. r=tabraldes
authorJim Mathies <jmathies@mozilla.com>
Wed, 20 Feb 2013 08:47:15 -0600
changeset 122458 c64083c5696d81a78093ab34ced518d6c84f74af
parent 122457 69e5c650ee7f4475b3b64c02352ee705e9a06c12
child 122459 3f2b219950b82780be2c88320ec4a7852b3c4988
push id24342
push userryanvm@gmail.com
push dateThu, 21 Feb 2013 13:05:06 +0000
treeherdermozilla-central@702d2814efbf [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerstabraldes
bugs793547
milestone22.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 793547 - Query the underlying data object if it exists for uri handed to the Win8 CEH in ShellExecute operations. Fixes some clipped url issues. r=tabraldes
browser/metro/shell/commandexecutehandler/CommandExecuteHandler.cpp
browser/metro/shell/commandexecutehandler/Makefile.in
--- a/browser/metro/shell/commandexecutehandler/CommandExecuteHandler.cpp
+++ b/browser/metro/shell/commandexecutehandler/CommandExecuteHandler.cpp
@@ -15,16 +15,17 @@
 #include <shlwapi.h>
 #include <propkey.h>
 #include <propvarutil.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <strsafe.h>
 #include <io.h>
 #include <shellapi.h>
+#include <wininet.h>
 
 #ifdef SHOW_CONSOLE
 #define DEBUG_DELAY_SHUTDOWN 1
 #endif
 
 // Heartbeat timer duration used while waiting for an incoming request.
 #define HEARTBEAT_MSEC 1000
 // Total number of heartbeats we wait before giving up and shutting down.
@@ -433,34 +434,101 @@ bool CExecuteCommandVerb::IsTargetBrowse
   checkPath.Append(L"\\");
   checkPath.Append(kFirefoxExe);
   if (tmpTarget == checkPath) {
     return true;
   }
   return false;
 }
 
+namespace {
+  const FORMATETC kPlainTextFormat =
+    {CF_TEXT, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
+  const FORMATETC kPlainTextWFormat =
+    {CF_UNICODETEXT, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
+}
+
+bool HasPlainText(IDataObject* aDataObj) {
+  return SUCCEEDED(aDataObj->QueryGetData((FORMATETC*)&kPlainTextWFormat)) ||
+      SUCCEEDED(aDataObj->QueryGetData((FORMATETC*)&kPlainTextFormat));
+}
+
+bool GetPlainText(IDataObject* aDataObj, CStringW& cstrText)
+{
+  if (!HasPlainText(aDataObj))
+    return false;
+
+  STGMEDIUM store;
+
+  // unicode text
+  if (SUCCEEDED(aDataObj->GetData((FORMATETC*)&kPlainTextWFormat, &store))) {
+    // makes a copy
+    cstrText = static_cast<LPCWSTR>(GlobalLock(store.hGlobal));
+    GlobalUnlock(store.hGlobal);
+    ReleaseStgMedium(&store);
+    return true;
+  }
+
+  // ascii text
+  if (SUCCEEDED(aDataObj->GetData((FORMATETC*)&kPlainTextFormat, &store))) {
+    // makes a copy
+    cstrText = static_cast<char*>(GlobalLock(store.hGlobal));
+    GlobalUnlock(store.hGlobal);
+    ReleaseStgMedium(&store);
+    return true;
+  }
+
+  return false;
+}
+
 /*
  * Updates the current target based on the contents of
  * a shell item.
  */
 bool CExecuteCommandVerb::SetTargetPath(IShellItem* aItem)
 {
   if (!aItem)
     return false;
 
+  CString cstrText;
+  CComPtr<IDataObject> object;
+  // Check the underlying data object first to insure we get
+  // absolute uri. See chromium bug 157184.
+  if (SUCCEEDED(aItem->BindToHandler(NULL, BHID_DataObject,
+                                     IID_IDataObject,
+                                     reinterpret_cast<void**>(&object))) &&
+      GetPlainText(object, cstrText)) {
+    wchar_t scheme[16];
+    URL_COMPONENTS components = {0};
+    components.lpszScheme = scheme;
+    components.dwSchemeLength = sizeof(scheme)/sizeof(scheme[0]);
+    components.dwStructSize = sizeof(components);
+    // note, more advanced use may have issues with paths with spaces.
+    if (!InternetCrackUrlW(cstrText, 0, 0, &components)) {
+      Log(L"Failed to identify object text '%s'", cstrText);
+      return false;
+    }
+
+    mTargetIsFileSystemLink = (components.nScheme == INTERNET_SCHEME_FILE);
+    mTarget = cstrText;
+    return true;
+  }
+
+  Log(L"No data object or data object has no text.");
+
+  // Use the shell item display name
   LPWSTR str = NULL;
   mTargetIsFileSystemLink = true;
   if (FAILED(aItem->GetDisplayName(SIGDN_FILESYSPATH, &str))) {
+    mTargetIsFileSystemLink = false;
     if (FAILED(aItem->GetDisplayName(SIGDN_URL, &str))) {
+      Log(L"Failed to get parameter string.");
       return false;
     }
-    mTargetIsFileSystemLink = false;
   }
-
   mTarget = str;
   CoTaskMemFree(str);
   return true;
 }
 
 /*
  * Desktop launch - Launch the destop browser to display the current
  * target using shellexecute.
--- a/browser/metro/shell/commandexecutehandler/Makefile.in
+++ b/browser/metro/shell/commandexecutehandler/Makefile.in
@@ -30,13 +30,14 @@ CPPSRCS	= \
 
 OS_LIBS = \
 	kernel32.lib \
 	user32.lib \
 	ole32.lib \
 	shlwapi.lib \
 	propsys.lib \
 	advapi32.lib \
+	wininet.lib \
 	$(NULL)
 
 DEFINES += -DUNICODE -D_UNICODE -DNS_NO_XPCOM
 
 include $(topsrcdir)/config/rules.mk