summaryrefslogtreecommitdiffstats
path: root/win8
diff options
context:
space:
mode:
authorrobertshield@chromium.org <robertshield@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-09-08 17:50:30 +0000
committerrobertshield@chromium.org <robertshield@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-09-08 17:50:30 +0000
commitd652bfa5646f4abd22b470a88478769c222c2177 (patch)
tree44f25d8b94f5c939df5ee12201ef6367b508ce25 /win8
parenta9e5f04481565af0a3c8dbe770b14899f24b68f7 (diff)
downloadchromium_src-d652bfa5646f4abd22b470a88478769c222c2177.zip
chromium_src-d652bfa5646f4abd22b470a88478769c222c2177.tar.gz
chromium_src-d652bfa5646f4abd22b470a88478769c222c2177.tar.bz2
Manually merging remaining Win8 changes.
BUG=127799 TEST=NONE Review URL: https://chromiumcodereview.appspot.com/10914160 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@155592 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'win8')
-rw-r--r--win8/delegate_execute/command_execute_impl.cc12
-rw-r--r--win8/delegate_execute/delegate_execute.cc110
-rw-r--r--win8/delegate_execute/delegate_execute_operation.cc44
-rw-r--r--win8/delegate_execute/delegate_execute_operation.h44
-rw-r--r--win8/metro_driver/chrome_app_view.cc135
-rw-r--r--win8/metro_driver/chrome_url_launch_handler.cc26
-rw-r--r--win8/metro_driver/metro_driver.gyp1
-rw-r--r--win8/metro_driver/secondary_tile.cc7
8 files changed, 283 insertions, 96 deletions
diff --git a/win8/delegate_execute/command_execute_impl.cc b/win8/delegate_execute/command_execute_impl.cc
index ef1378a..9781386 100644
--- a/win8/delegate_execute/command_execute_impl.cc
+++ b/win8/delegate_execute/command_execute_impl.cc
@@ -220,7 +220,7 @@ STDMETHODIMP CommandExecuteImpl::Execute() {
AtlTrace("Activating for file\n");
hr = activation_manager->ActivateApplication(app_id.c_str(),
verb_.c_str(),
- AO_NOERRORUI,
+ AO_NONE,
&pid);
} else {
AtlTrace("Activating for protocol\n");
@@ -388,6 +388,7 @@ HRESULT CommandExecuteImpl::LaunchDesktopChrome() {
&proc_info);
if (ret) {
AtlTrace("Process id is %d\n", proc_info.dwProcessId);
+ AllowSetForegroundWindow(proc_info.dwProcessId);
CloseHandle(proc_info.hProcess);
CloseHandle(proc_info.hThread);
} else {
@@ -417,8 +418,15 @@ EC_HOST_UI_MODE CommandExecuteImpl::GetLaunchMode() {
if (parameters_ == ASCIIToWide(switches::kForceImmersive)) {
launch_mode = ECHUIM_IMMERSIVE;
- AtlTrace("Launch mode forced to %s\n", modes[launch_mode]);
launch_mode_determined = true;
+ } else if (parameters_ == ASCIIToWide(switches::kForceDesktop)) {
+ launch_mode = ECHUIM_DESKTOP;
+ launch_mode_determined = true;
+ }
+
+ if (launch_mode_determined) {
+ parameters_.clear();
+ AtlTrace("Launch mode forced to %s\n", modes[launch_mode]);
return launch_mode;
}
diff --git a/win8/delegate_execute/delegate_execute.cc b/win8/delegate_execute/delegate_execute.cc
index 9f3430c..249ad5b 100644
--- a/win8/delegate_execute/delegate_execute.cc
+++ b/win8/delegate_execute/delegate_execute.cc
@@ -11,8 +11,8 @@
#include "base/at_exit.h"
#include "base/command_line.h"
#include "base/file_util.h"
+#include "base/process_util.h"
#include "base/string16.h"
-#include "base/string_number_conversions.h"
#include "base/utf_string_conversions.h"
#include "base/win/scoped_com_initializer.h"
#include "base/win/scoped_handle.h"
@@ -53,68 +53,74 @@ class DelegateExecuteModule
DelegateExecuteModule _AtlModule;
-// Relaunch metro Chrome by ShellExecute on |shortcut| with --force-immersive.
-// |handle_value| is an optional handle on which this function will wait before
-// performing the relaunch.
-int RelaunchChrome(const FilePath& shortcut, const string16& handle_value) {
- base::win::ScopedHandle handle;
-
- if (!handle_value.empty()) {
- uint32 the_handle = 0;
- if (!base::StringToUint(handle_value, &the_handle)) {
- // Failed to parse the handle value. Skip the wait but proceed with the
- // relaunch.
- AtlTrace(L"Failed to parse handle value %ls\n", handle_value.c_str());
+using delegate_execute::DelegateExecuteOperation;
+using base::win::ScopedHandle;
+
+int RelaunchChrome(const DelegateExecuteOperation& operation) {
+ AtlTrace("Relaunching [%ls] with flags [%s]\n",
+ operation.mutex().c_str(), operation.relaunch_flags());
+ ScopedHandle mutex(OpenMutexW(SYNCHRONIZE, FALSE, operation.mutex().c_str()));
+ if (mutex.IsValid()) {
+ const int kWaitSeconds = 5;
+ DWORD result = ::WaitForSingleObject(mutex, kWaitSeconds * 1000);
+ if (result == WAIT_ABANDONED) {
+ // This is the normal case. Chrome exits and windows marks the mutex as
+ // abandoned.
+ } else if (result == WAIT_OBJECT_0) {
+ // This is unexpected. Check if somebody is not closing the mutex on
+ // RelaunchChromehelper, the mutex should not be closed.
+ AtlTrace("Unexpected release of the relaunch mutex!!\n");
+ } else if (result == WAIT_TIMEOUT) {
+ // This could mean that Chrome is hung. Proceed to exterminate.
+ DWORD pid = operation.GetParentPid();
+ AtlTrace("%ds timeout. Killing Chrome %d\n", kWaitSeconds, pid);
+ base::KillProcessById(pid, 0, false);
} else {
- handle.Set(reinterpret_cast<HANDLE>(the_handle));
+ AtlTrace("Failed to wait for relaunch mutex, result is 0x%x\n", result);
}
- }
-
- if (handle.IsValid()) {
- AtlTrace(L"Waiting for chrome.exe to exit.\n");
- DWORD result = ::WaitForSingleObject(handle, 10 * 1000);
- AtlTrace(L"And we're back.\n");
- if (result != WAIT_OBJECT_0) {
- AtlTrace(L"Failed to wait for parent to exit; result=%u.\n", result);
- // This could mean that Chrome has hung. Conservatively proceed with
- // the relaunch anyway.
- }
- handle.Close();
+ } else {
+ // It is possible that chrome exits so fast that the mutex is not there.
+ AtlTrace("No relaunch mutex found\n");
}
base::win::ScopedCOMInitializer com_initializer;
- AtlTrace(L"Launching Chrome via %ls.\n", shortcut.value().c_str());
- int ser = reinterpret_cast<int>(
- ::ShellExecute(NULL, NULL, shortcut.value().c_str(),
- ASCIIToWide(switches::kForceImmersive).c_str(), NULL,
- SW_SHOWNORMAL));
- AtlTrace(L"ShellExecute returned %d.\n", ser);
- return ser <= 32;
+ string16 flags(ASCIIToWide(operation.relaunch_flags()));
+ SHELLEXECUTEINFO sei = { sizeof(sei) };
+ sei.fMask = SEE_MASK_FLAG_LOG_USAGE;
+ sei.nShow = SW_SHOWNORMAL;
+ sei.lpFile = operation.shortcut().value().c_str();
+ sei.lpParameters = flags.c_str();
+
+ AtlTrace(L"Relaunching Chrome via shortcut [%ls]\n", sei.lpFile);
+
+ if (!::ShellExecuteExW(&sei)) {
+ int error = HRESULT_FROM_WIN32(::GetLastError());
+ AtlTrace("ShellExecute returned 0x%08X\n", error);
+ return error;
+ }
+ return S_OK;
}
-//
-extern "C" int WINAPI _tWinMain(HINSTANCE , HINSTANCE,
- LPTSTR, int nShowCmd) {
- using delegate_execute::DelegateExecuteOperation;
+extern "C" int WINAPI _tWinMain(HINSTANCE , HINSTANCE, LPTSTR, int nShowCmd) {
base::AtExitManager exit_manager;
+ AtlTrace("delegate_execute enter\n");
CommandLine::Init(0, NULL);
- CommandLine* cmd_line = CommandLine::ForCurrentProcess();
+ HRESULT ret_code = E_UNEXPECTED;
DelegateExecuteOperation operation;
-
- operation.Initialize(cmd_line);
- switch (operation.operation_type()) {
- case DelegateExecuteOperation::EXE_MODULE:
- return _AtlModule.WinMain(nShowCmd);
-
- case DelegateExecuteOperation::RELAUNCH_CHROME:
- return RelaunchChrome(operation.relaunch_shortcut(),
- cmd_line->GetSwitchValueNative(switches::kWaitForHandle));
-
- default:
- NOTREACHED();
+ if (operation.Init(CommandLine::ForCurrentProcess())) {
+ switch (operation.operation_type()) {
+ case DelegateExecuteOperation::DELEGATE_EXECUTE:
+ ret_code = _AtlModule.WinMain(nShowCmd);
+ break;
+ case DelegateExecuteOperation::RELAUNCH_CHROME:
+ ret_code = RelaunchChrome(operation);
+ break;
+ default:
+ NOTREACHED();
+ }
}
-
- return 1;
+ AtlTrace("delegate_execute exit, code = %d\n", ret_code);
+ return ret_code;
}
diff --git a/win8/delegate_execute/delegate_execute_operation.cc b/win8/delegate_execute/delegate_execute_operation.cc
index e6823f0..f2ba2c4 100644
--- a/win8/delegate_execute/delegate_execute_operation.cc
+++ b/win8/delegate_execute/delegate_execute_operation.cc
@@ -5,33 +5,49 @@
#include "win8/delegate_execute/delegate_execute_operation.h"
#include "base/command_line.h"
+#include "base/string_number_conversions.h"
+#include "base/string_split.h"
#include "chrome/common/chrome_switches.h"
namespace delegate_execute {
DelegateExecuteOperation::DelegateExecuteOperation()
- : operation_type_(EXE_MODULE) {
+ : operation_type_(DELEGATE_EXECUTE),
+ relaunch_flags_("") {
}
DelegateExecuteOperation::~DelegateExecuteOperation() {
- Clear();
}
-void DelegateExecuteOperation::Initialize(const CommandLine* command_line) {
- Clear();
-
- // --relaunch-shortcut=PathToShortcut triggers the relaunch Chrome operation.
- FilePath shortcut(
- command_line->GetSwitchValuePath(switches::kRelaunchShortcut));
- if (!shortcut.empty()) {
- relaunch_shortcut_ = shortcut;
- operation_type_ = RELAUNCH_CHROME;
+bool DelegateExecuteOperation::Init(const CommandLine* cmd_line) {
+ FilePath shortcut(cmd_line->GetSwitchValuePath(switches::kRelaunchShortcut));
+ if (shortcut.empty()) {
+ operation_type_ = DELEGATE_EXECUTE;
+ return true;
}
+ relaunch_shortcut_ = shortcut;
+ mutex_ = cmd_line->GetSwitchValueNative(switches::kWaitForMutex);
+ if (mutex_.empty())
+ return false;
+ // Add the mode forcing flags, if any.
+ if (cmd_line->HasSwitch(switches::kForceDesktop))
+ relaunch_flags_ = switches::kForceDesktop;
+ else if (cmd_line->HasSwitch(switches::kForceImmersive))
+ relaunch_flags_ = switches::kForceImmersive;
+
+ operation_type_ = RELAUNCH_CHROME;
+ return true;
}
-void DelegateExecuteOperation::Clear() {
- operation_type_ = EXE_MODULE;
- relaunch_shortcut_.clear();
+DWORD DelegateExecuteOperation::GetParentPid() const {
+ std::vector<string16> parts;
+ base::SplitString(mutex_, L'.', &parts);
+ if (parts.size() != 3)
+ return 0;
+ DWORD pid;
+ if (!base::StringToUint(parts[2], reinterpret_cast<uint32*>(&pid)))
+ return 0;
+ return pid;
}
} // namespace delegate_execute
diff --git a/win8/delegate_execute/delegate_execute_operation.h b/win8/delegate_execute/delegate_execute_operation.h
index 59acfd7a..f2f01cc 100644
--- a/win8/delegate_execute/delegate_execute_operation.h
+++ b/win8/delegate_execute/delegate_execute_operation.h
@@ -6,44 +6,70 @@
#define WIN8_DELEGATE_EXECUTE_DELEGATE_EXECUTE_OPERATION_H_
#include <atldef.h>
+#include <windows.h>
#include "base/basictypes.h"
#include "base/file_path.h"
+#include "base/string16.h"
class CommandLine;
namespace delegate_execute {
// Parses a portion of the DelegateExecute handler's command line to determine
-// the desired operation.
+// the desired operation. The operation type is decided by looking at the
+// command line. The operations are:
+// DELEGATE_EXECUTE:
+// When the delegate_execute.exe is invoked by windows when a chrome
+// activation via the shell, possibly using ShellExecute. Control must
+// be given to ATLs WinMain.
+// RELAUNCH_CHROME:
+// When the delegate_execute.exe is launched by chrome, when chrome needs
+// to re-launch itself. The required command line parameters are:
+// --relaunch-shortcut=<PathToShortcut>
+// --wait-for-mutex=<MutexNamePid>
+// The PathToShortcut must be the fully qualified file name to the chrome
+// shortcut that has the appId and other 'metro ready' parameters.
+// The MutexNamePid is a mutex name that also encodes the process id and
+// must follow the format <A>.<B>.<pid> where A and B are arbitray strings
+// (usually chrome.relaunch) and pid is the process id of chrome.
class DelegateExecuteOperation {
public:
enum OperationType {
- EXE_MODULE,
+ DELEGATE_EXECUTE,
RELAUNCH_CHROME,
};
DelegateExecuteOperation();
~DelegateExecuteOperation();
- void Initialize(const CommandLine* command_line);
+ bool Init(const CommandLine* cmd_line);
OperationType operation_type() const {
return operation_type_;
}
- // Returns the argument to the --relaunch-shortcut switch. Valid only when
- // the operation is RELAUNCH_CHROME.
- const FilePath& relaunch_shortcut() const {
- ATLASSERT(operation_type_ == RELAUNCH_CHROME);
+ const char* relaunch_flags() const {
+ return relaunch_flags_;
+ }
+
+ const string16& mutex() const {
+ return mutex_;
+ }
+
+ // Returns the process id of the parent or 0 on failure.
+ DWORD GetParentPid() const;
+
+ const FilePath& shortcut() const {
return relaunch_shortcut_;
}
private:
- void Clear();
-
OperationType operation_type_;
+ const char* relaunch_flags_;
FilePath relaunch_shortcut_;
+ string16 mutex_;
+
DISALLOW_COPY_AND_ASSIGN(DelegateExecuteOperation);
};
diff --git a/win8/metro_driver/chrome_app_view.cc b/win8/metro_driver/chrome_app_view.cc
index 7d5580e..e2ec21a 100644
--- a/win8/metro_driver/chrome_app_view.cc
+++ b/win8/metro_driver/chrome_app_view.cc
@@ -56,8 +56,97 @@ const wchar_t kOSKClassName[] = L"IPTip_Main_Window";
static const int kOSKAdjustmentOffset = 20;
+const wchar_t kChromeSubclassWindowProp[] = L"MetroChromeWindowProc";
+
namespace {
+enum Modifier {
+ NONE,
+ SHIFT = 1,
+ CONTROL = 2,
+ ALT = 4
+};
+
+// Helper function to send keystrokes via the SendInput function.
+// Params:
+// mnemonic_char: The keystroke to be sent.
+// modifiers: Combination with Alt, Ctrl, Shift, etc.
+// extended: whether this is an extended key.
+// unicode: whether this is a unicode key.
+void SendMnemonic(WORD mnemonic_char, Modifier modifiers, bool extended,
+ bool unicode) {
+ INPUT keys[4] = {0}; // Keyboard events
+ int key_count = 0; // Number of generated events
+
+ if (modifiers & SHIFT) {
+ keys[key_count].type = INPUT_KEYBOARD;
+ keys[key_count].ki.wVk = VK_SHIFT;
+ keys[key_count].ki.wScan = MapVirtualKey(VK_SHIFT, 0);
+ key_count++;
+ }
+
+ if (modifiers & CONTROL) {
+ keys[key_count].type = INPUT_KEYBOARD;
+ keys[key_count].ki.wVk = VK_CONTROL;
+ keys[key_count].ki.wScan = MapVirtualKey(VK_CONTROL, 0);
+ key_count++;
+ }
+
+ if (modifiers & ALT) {
+ keys[key_count].type = INPUT_KEYBOARD;
+ keys[key_count].ki.wVk = VK_MENU;
+ keys[key_count].ki.wScan = MapVirtualKey(VK_MENU, 0);
+ key_count++;
+ }
+
+ keys[key_count].type = INPUT_KEYBOARD;
+ keys[key_count].ki.wVk = mnemonic_char;
+ keys[key_count].ki.wScan = MapVirtualKey(mnemonic_char, 0);
+
+ if (extended)
+ keys[key_count].ki.dwFlags |= KEYEVENTF_EXTENDEDKEY;
+ if (unicode)
+ keys[key_count].ki.dwFlags |= KEYEVENTF_UNICODE;
+ key_count++;
+
+ bool should_sleep = key_count > 1;
+
+ // Send key downs
+ for (int i = 0; i < key_count; i++) {
+ SendInput(1, &keys[ i ], sizeof(keys[0]));
+ keys[i].ki.dwFlags |= KEYEVENTF_KEYUP;
+ if (should_sleep) {
+ Sleep(10);
+ }
+ }
+
+ // Now send key ups in reverse order
+ for (int i = key_count; i; i--) {
+ SendInput(1, &keys[ i - 1 ], sizeof(keys[0]));
+ if (should_sleep) {
+ Sleep(10);
+ }
+ }
+}
+
+void MetroExit() {
+ if (globals.core_window == ::GetForegroundWindow()) {
+ DVLOG(1) << "We are in the foreground. Exiting via Alt F4";
+ SendMnemonic(VK_F4, ALT, false, false);
+ DWORD core_window_process_id = 0;
+ DWORD core_window_thread_id = GetWindowThreadProcessId(
+ globals.core_window, &core_window_process_id);
+ if (core_window_thread_id != ::GetCurrentThreadId()) {
+ // Sleep to give time to the core window thread to get this message.
+ Sleep(100);
+ }
+ } else {
+ DVLOG(1) << "We are not in the foreground. Exiting normally";
+ globals.app_exit->Exit();
+ globals.core_window = NULL;
+ }
+}
+
void AdjustToFitWindow(HWND hwnd, int flags) {
RECT rect = {0};
::GetWindowRect(globals.core_window, &rect);
@@ -69,6 +158,35 @@ void AdjustToFitWindow(HWND hwnd, int flags) {
SWP_NOZORDER | flags);
}
+LRESULT CALLBACK ChromeWindowProc(HWND window,
+ UINT message,
+ WPARAM wp,
+ LPARAM lp) {
+ if (message == WM_SETCURSOR) {
+ // Override the WM_SETCURSOR message to avoid showing the resize cursor
+ // as the mouse moves to the edge of the screen.
+ switch (LOWORD(lp)) {
+ case HTBOTTOM:
+ case HTBOTTOMLEFT:
+ case HTBOTTOMRIGHT:
+ case HTLEFT:
+ case HTRIGHT:
+ case HTTOP:
+ case HTTOPLEFT:
+ case HTTOPRIGHT:
+ lp = MAKELPARAM(HTCLIENT, HIWORD(lp));
+ break;
+ default:
+ break;
+ }
+ }
+
+ WNDPROC old_proc = reinterpret_cast<WNDPROC>(
+ ::GetProp(window, kChromeSubclassWindowProp));
+ DCHECK(old_proc);
+ return CallWindowProc(old_proc, window, message, wp, lp);
+}
+
void AdjustFrameWindowStyleForMetro(HWND hwnd) {
DVLOG(1) << __FUNCTION__;
// Ajust the frame so the live preview works and the frame buttons dissapear.
@@ -78,6 +196,14 @@ void AdjustFrameWindowStyleForMetro(HWND hwnd) {
::SetWindowLong(hwnd, GWL_EXSTYLE,
::GetWindowLong(hwnd, GWL_EXSTYLE) & ~(WS_EX_DLGMODALFRAME |
WS_EX_WINDOWEDGE | WS_EX_CLIENTEDGE | WS_EX_STATICEDGE));
+
+ // Subclass the wndproc of the frame window, if it's not already there.
+ if (::GetProp(hwnd, kChromeSubclassWindowProp) == NULL) {
+ WNDPROC old_chrome_proc = reinterpret_cast<WNDPROC>(
+ ::SetWindowLong(hwnd, GWL_WNDPROC,
+ reinterpret_cast<long>(ChromeWindowProc)));
+ ::SetProp(hwnd, kChromeSubclassWindowProp, old_chrome_proc);
+ }
AdjustToFitWindow(hwnd, SWP_FRAMECHANGED | SWP_NOACTIVATE);
}
@@ -117,7 +243,7 @@ void CloseFrameWindowInternal(HWND hwnd) {
} else {
// time to quit
DVLOG(1) << "Last host window closed. Calling Exit().";
- globals.app_exit->Exit();
+ MetroExit();
}
}
@@ -486,8 +612,9 @@ DWORD WINAPI HostMainThreadProc(void*) {
::SetWindowLong(globals.core_window, GWL_WNDPROC,
reinterpret_cast<long>(ChromeAppView::CoreWindowProc)));
DWORD exit_code = globals.host_main(globals.host_context);
+
DVLOG(1) << "host thread done, exit_code=" << exit_code;
- globals.app_exit->Exit();
+ MetroExit();
return exit_code;
}
@@ -696,9 +823,11 @@ ChromeAppView::Run() {
if (wr != WAIT_OBJECT_0) {
DVLOG(1) << "Waiting for host thread failed : " << wr;
}
+
+ DVLOG(1) << "Host thread exited";
+
::CloseHandle(globals.host_thread);
globals.host_thread = NULL;
-
return hr;
}
diff --git a/win8/metro_driver/chrome_url_launch_handler.cc b/win8/metro_driver/chrome_url_launch_handler.cc
index 866bccc..7a9a607 100644
--- a/win8/metro_driver/chrome_url_launch_handler.cc
+++ b/win8/metro_driver/chrome_url_launch_handler.cc
@@ -11,7 +11,7 @@
#include <shlobj.h>
#include <string>
-#include "base/string_tokenizer.h"
+#include "base/command_line.h"
#include "winrt_utils.h"
@@ -97,22 +97,18 @@ void ChromeUrlLaunchHandler::HandleProtocolLaunch(
InitiateNavigationOrSearchRequest(globals.navigation_url.c_str(), 0);
}
-// The LaunchArgs are in a semi-color separated key_name=key_value list. At
-// the moment the only key_name understaood is "url".
+// |launch_args| is an encoded command line, minus the executable name. To
+// find the URL to launch the first argument is used. If any other parameters
+// are encoded in |launch_args| they are ignored.
string16 ChromeUrlLaunchHandler::GetUrlFromLaunchArgs(
const string16& launch_args) {
- WStringTokenizer tokenizer(launch_args, L";=");
- bool next_is_url = false;
- while (tokenizer.GetNext()) {
- if (next_is_url)
- return tokenizer.token();
- if (tokenizer.token() == L"url")
- next_is_url = true;
- }
- if (launch_args == L"opennewwindow") {
- DVLOG(1) << "Returning new tab url";
- return L"chrome://newtab";
- }
+ string16 dummy_command_line(L"dummy.exe ");
+ dummy_command_line.append(launch_args);
+ CommandLine command_line = CommandLine::FromString(dummy_command_line);
+ CommandLine::StringVector args = command_line.GetArgs();
+ if (args.size() > 0)
+ return args[0];
+
return string16();
}
diff --git a/win8/metro_driver/metro_driver.gyp b/win8/metro_driver/metro_driver.gyp
index 186d2bd..94960cdf 100644
--- a/win8/metro_driver/metro_driver.gyp
+++ b/win8/metro_driver/metro_driver.gyp
@@ -31,6 +31,7 @@
'type': 'shared_library',
'dependencies': [
'../../base/base.gyp:base',
+ '../../build/temp_gyp/googleurl.gyp:googleurl',
'../../crypto/crypto.gyp:crypto',
'../../sandbox/sandbox.gyp:sandbox',
'../../google_update/google_update.gyp:google_update',
diff --git a/win8/metro_driver/secondary_tile.cc b/win8/metro_driver/secondary_tile.cc
index 8a54bd7..c784fdc 100644
--- a/win8/metro_driver/secondary_tile.cc
+++ b/win8/metro_driver/secondary_tile.cc
@@ -15,6 +15,7 @@
#include "base/string_number_conversions.h"
#include "base/utf_string_conversions.h"
#include "crypto/sha2.h"
+#include "googleurl/src/gurl.h"
#include "win8/metro_driver/chrome_app_view.h"
#include "win8/metro_driver/winrt_utils.h"
@@ -91,7 +92,11 @@ void CreateTileOnStartScreen(const string16& title_str,
mswrw::HString id;
id.Attach(MakeHString(GenerateTileId(url_str)));
mswrw::HString args;
- args.Attach(MakeHString(string16(L"url=").append(url_str)));
+ // The url is just passed into the tile agruments as is. Metro and desktop
+ // chrome will see the arguments as command line parameters.
+ // A GURL is used to ensure any spaces are properly escaped.
+ GURL url(url_str);
+ args.Attach(MakeHString(UTF8ToUTF16(url.spec())));
mswr::ComPtr<winfoundtn::IUriRuntimeClassFactory> uri_factory;
hr = winrt_utils::CreateActivationFactory(