| // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "stdafx.h" |
| #include "chrome_url_launch_handler.h" |
| #include "chrome_app_view.h" |
| |
| #include <assert.h> |
| #include <shellapi.h> |
| #include <shlobj.h> |
| #include <string> |
| |
| #include "base/command_line.h" |
| |
| #include "winrt_utils.h" |
| |
| typedef winfoundtn::ITypedEventHandler< |
| winapp::Search::SearchPane*, |
| winapp::Search::SearchPaneQuerySubmittedEventArgs*> QuerySubmittedHandler; |
| |
| ChromeUrlLaunchHandler::ChromeUrlLaunchHandler() { |
| globals.is_initial_activation = true; |
| globals.initial_activation_kind = winapp::Activation::ActivationKind_Launch; |
| DVLOG(1) << __FUNCTION__; |
| } |
| |
| // TODO(ananta) |
| // Remove this once we consolidate metro driver with chrome. |
| const wchar_t kMetroNavigationAndSearchMessage[] = |
| L"CHROME_METRO_NAV_SEARCH_REQUEST"; |
| |
| ChromeUrlLaunchHandler::~ChromeUrlLaunchHandler() { |
| DVLOG(1) << __FUNCTION__; |
| search_pane_->remove_QuerySubmitted(query_submitted_token_); |
| } |
| |
| HRESULT ChromeUrlLaunchHandler::Initialize() { |
| mswr::ComPtr<winapp::Search::ISearchPaneStatics> search_pane_statics; |
| HRESULT hr = winrt_utils::CreateActivationFactory( |
| RuntimeClass_Windows_ApplicationModel_Search_SearchPane, |
| search_pane_statics.GetAddressOf()); |
| CheckHR(hr, "Failed to activate ISearchPaneStatics"); |
| |
| hr = search_pane_statics->GetForCurrentView(&search_pane_); |
| if (FAILED(hr)) { |
| LOG(ERROR) << "Failed to get search pane for current view"; |
| return hr; |
| } |
| |
| hr = search_pane_->add_QuerySubmitted(mswr::Callback<QuerySubmittedHandler>( |
| this, |
| &ChromeUrlLaunchHandler::OnQuerySubmitted).Get(), |
| &query_submitted_token_); |
| if (FAILED(hr)) { |
| LOG(ERROR) << "Failed to register for Query Submitted event"; |
| return hr; |
| } |
| return hr; |
| } |
| |
| HRESULT ChromeUrlLaunchHandler::OnQuerySubmitted( |
| winapp::Search::ISearchPane* search_pane, |
| winapp::Search::ISearchPaneQuerySubmittedEventArgs* args) { |
| DVLOG(1) << "OnQuerySubmitted"; |
| HandleSearchRequest(args); |
| return S_OK; |
| } |
| |
| template<class T> |
| void ChromeUrlLaunchHandler::HandleSearchRequest(T* args) { |
| DVLOG(1) << __FUNCTION__; |
| mswrw::HString search_string; |
| args->get_QueryText(search_string.GetAddressOf()); |
| base::string16 search_text(MakeStdWString(search_string.Get())); |
| globals.search_string = search_text; |
| DVLOG(1) << search_text.c_str(); |
| // If this is the initial activation then we wait for Chrome to initiate the |
| // navigation. In all other cases navigate right away. |
| if (!globals.is_initial_activation) |
| InitiateNavigationOrSearchRequest(NULL, globals.search_string.c_str()); |
| } |
| |
| void ChromeUrlLaunchHandler::HandleProtocolLaunch( |
| winapp::Activation::IProtocolActivatedEventArgs* args) { |
| DVLOG(1) << __FUNCTION__; |
| mswr::ComPtr<winfoundtn::IUriRuntimeClass> uri; |
| args->get_Uri(&uri); |
| mswrw::HString url; |
| uri->get_AbsoluteUri(url.GetAddressOf()); |
| base::string16 actual_url(MakeStdWString(url.Get())); |
| globals.navigation_url = actual_url; |
| |
| // If this is the initial activation then we wait for Chrome to initiate the |
| // navigation. In all other cases navigate right away. |
| if (!globals.is_initial_activation) |
| InitiateNavigationOrSearchRequest(globals.navigation_url.c_str(), 0); |
| } |
| |
| // |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. |
| base::string16 ChromeUrlLaunchHandler::GetUrlFromLaunchArgs( |
| const base::string16& launch_args) { |
| if (launch_args == L"opennewwindow") { |
| VLOG(1) << "Returning new tab url"; |
| return L"chrome://newtab"; |
| } |
| base::string16 dummy_command_line(L"dummy.exe "); |
| dummy_command_line.append(launch_args); |
| base::CommandLine command_line = |
| base::CommandLine::FromString(dummy_command_line); |
| base::CommandLine::StringVector args = command_line.GetArgs(); |
| if (args.size() > 0) |
| return args[0]; |
| |
| return base::string16(); |
| } |
| |
| void ChromeUrlLaunchHandler::HandleLaunch( |
| winapp::Activation::ILaunchActivatedEventArgs* args) { |
| mswrw::HString launch_args; |
| args->get_Arguments(launch_args.GetAddressOf()); |
| base::string16 actual_launch_args(MakeStdWString(launch_args.Get())); |
| globals.navigation_url = GetUrlFromLaunchArgs(actual_launch_args); |
| DVLOG(1) << __FUNCTION__ << ", launch_args=" << actual_launch_args |
| << ", url=" << globals.navigation_url |
| << ", is_initial_activation=" << globals.is_initial_activation; |
| |
| // If this is the initial launch then we wait for Chrome to initiate the |
| // navigation. In all other cases navigate right away. |
| if (!globals.is_initial_activation) |
| InitiateNavigationOrSearchRequest(globals.navigation_url.c_str(), 0); |
| } |
| |
| void ChromeUrlLaunchHandler::Activate( |
| winapp::Activation::IActivatedEventArgs* args) { |
| winapp::Activation::ActivationKind activation_kind; |
| CheckHR(args->get_Kind(&activation_kind)); |
| |
| DVLOG(1) << __FUNCTION__ << ", activation_kind=" << activation_kind; |
| |
| if (globals.is_initial_activation) |
| globals.initial_activation_kind = activation_kind; |
| |
| if (activation_kind == winapp::Activation::ActivationKind_Launch) { |
| mswr::ComPtr<winapp::Activation::ILaunchActivatedEventArgs> launch_args; |
| if (args->QueryInterface(winapp::Activation::IID_ILaunchActivatedEventArgs, |
| &launch_args) == S_OK) { |
| DVLOG(1) << "Activate: ActivationKind_Launch"; |
| HandleLaunch(launch_args.Get()); |
| } |
| } else if (activation_kind == |
| winapp::Activation::ActivationKind_Search) { |
| mswr::ComPtr<winapp::Activation::ISearchActivatedEventArgs> search_args; |
| if (args->QueryInterface(winapp::Activation::IID_ISearchActivatedEventArgs, |
| &search_args) == S_OK) { |
| DVLOG(1) << "Activate: ActivationKind_Search"; |
| HandleSearchRequest(search_args.Get()); |
| } |
| } else if (activation_kind == |
| winapp::Activation::ActivationKind_Protocol) { |
| mswr::ComPtr<winapp::Activation::IProtocolActivatedEventArgs> |
| protocol_args; |
| if (args->QueryInterface( |
| winapp::Activation::IID_IProtocolActivatedEventArgs, |
| &protocol_args) == S_OK) { |
| DVLOG(1) << "Activate: ActivationKind_Protocol"; |
| HandleProtocolLaunch(protocol_args.Get()); |
| } |
| } else { |
| DVLOG(1) << "Activate: Unhandled mode: " << activation_kind; |
| } |
| } |
| |
| void ChromeUrlLaunchHandler::InitiateNavigationOrSearchRequest( |
| const wchar_t* url, const wchar_t* search_string) { |
| DVLOG(1) << __FUNCTION__; |
| if (!url && !search_string) { |
| NOTREACHED(); |
| return; |
| } |
| |
| DVLOG(1) << (url ? url : L"NULL url"); |
| DVLOG(1) << (search_string ? search_string : L"NULL search string"); |
| |
| if (globals.host_windows.empty()) { |
| DVLOG(1) << "No chrome windows registered. Ignoring nav request"; |
| return; |
| } |
| |
| // Custom registered message to navigate or search in chrome. WPARAM |
| // points to the URL and LPARAM contains the search string. They are |
| // mutually exclusive. |
| static const UINT navigation_search_message = |
| RegisterWindowMessage(kMetroNavigationAndSearchMessage); |
| |
| if (url) { |
| VLOG(1) << "Posting url:" << url; |
| PostMessage(globals.host_windows.front().first, navigation_search_message, |
| reinterpret_cast<WPARAM>(url), 0); |
| } else { |
| VLOG(1) << "Posting search string:" << search_string; |
| PostMessage(globals.host_windows.front().first, navigation_search_message, |
| 0, reinterpret_cast<LPARAM>(search_string)); |
| } |
| } |