Home | History | Annotate | Download | only in metro_driver
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "stdafx.h"
      6 #include "chrome_url_launch_handler.h"
      7 #include "chrome_app_view.h"
      8 
      9 #include <assert.h>
     10 #include <shellapi.h>
     11 #include <shlobj.h>
     12 #include <string>
     13 
     14 #include "base/command_line.h"
     15 
     16 #include "winrt_utils.h"
     17 
     18 typedef winfoundtn::ITypedEventHandler<
     19     winapp::Search::SearchPane*,
     20     winapp::Search::SearchPaneQuerySubmittedEventArgs*> QuerySubmittedHandler;
     21 
     22 ChromeUrlLaunchHandler::ChromeUrlLaunchHandler() {
     23   globals.is_initial_activation = true;
     24   globals.initial_activation_kind = winapp::Activation::ActivationKind_Launch;
     25   DVLOG(1) << __FUNCTION__;
     26 }
     27 
     28 // TODO(ananta)
     29 // Remove this once we consolidate metro driver with chrome.
     30 const wchar_t kMetroNavigationAndSearchMessage[] =
     31     L"CHROME_METRO_NAV_SEARCH_REQUEST";
     32 
     33 ChromeUrlLaunchHandler::~ChromeUrlLaunchHandler() {
     34   DVLOG(1) << __FUNCTION__;
     35   search_pane_->remove_QuerySubmitted(query_submitted_token_);
     36 }
     37 
     38 HRESULT ChromeUrlLaunchHandler::Initialize() {
     39   mswr::ComPtr<winapp::Search::ISearchPaneStatics> search_pane_statics;
     40   HRESULT hr = winrt_utils::CreateActivationFactory(
     41       RuntimeClass_Windows_ApplicationModel_Search_SearchPane,
     42       search_pane_statics.GetAddressOf());
     43   CheckHR(hr, "Failed to activate ISearchPaneStatics");
     44 
     45   hr = search_pane_statics->GetForCurrentView(&search_pane_);
     46   if (FAILED(hr)) {
     47     LOG(ERROR) << "Failed to get search pane for current view";
     48     return hr;
     49   }
     50 
     51   hr = search_pane_->add_QuerySubmitted(mswr::Callback<QuerySubmittedHandler>(
     52       this,
     53       &ChromeUrlLaunchHandler::OnQuerySubmitted).Get(),
     54       &query_submitted_token_);
     55   if (FAILED(hr)) {
     56     LOG(ERROR) << "Failed to register for Query Submitted event";
     57     return hr;
     58   }
     59   return hr;
     60 }
     61 
     62 HRESULT ChromeUrlLaunchHandler::OnQuerySubmitted(
     63     winapp::Search::ISearchPane* search_pane,
     64     winapp::Search::ISearchPaneQuerySubmittedEventArgs* args) {
     65   DVLOG(1) << "OnQuerySubmitted";
     66   HandleSearchRequest(args);
     67   return S_OK;
     68 }
     69 
     70 template<class T>
     71 void ChromeUrlLaunchHandler::HandleSearchRequest(T* args) {
     72   DVLOG(1) << __FUNCTION__;
     73   mswrw::HString search_string;
     74   args->get_QueryText(search_string.GetAddressOf());
     75   base::string16 search_text(MakeStdWString(search_string.Get()));
     76   globals.search_string = search_text;
     77   DVLOG(1) << search_text.c_str();
     78   // If this is the initial activation then we wait for Chrome to initiate the
     79   // navigation. In all other cases navigate right away.
     80   if (!globals.is_initial_activation)
     81     InitiateNavigationOrSearchRequest(NULL, globals.search_string.c_str());
     82 }
     83 
     84 void ChromeUrlLaunchHandler::HandleProtocolLaunch(
     85     winapp::Activation::IProtocolActivatedEventArgs* args) {
     86   DVLOG(1) << __FUNCTION__;
     87   mswr::ComPtr<winfoundtn::IUriRuntimeClass> uri;
     88   args->get_Uri(&uri);
     89   mswrw::HString url;
     90   uri->get_AbsoluteUri(url.GetAddressOf());
     91   base::string16 actual_url(MakeStdWString(url.Get()));
     92   globals.navigation_url = actual_url;
     93 
     94   // If this is the initial activation then we wait for Chrome to initiate the
     95   // navigation. In all other cases navigate right away.
     96   if (!globals.is_initial_activation)
     97     InitiateNavigationOrSearchRequest(globals.navigation_url.c_str(), 0);
     98 }
     99 
    100 // |launch_args| is an encoded command line, minus the executable name. To
    101 // find the URL to launch the first argument is used. If any other parameters
    102 // are encoded in |launch_args| they are ignored.
    103 base::string16 ChromeUrlLaunchHandler::GetUrlFromLaunchArgs(
    104     const base::string16& launch_args) {
    105   if (launch_args == L"opennewwindow") {
    106     VLOG(1) << "Returning new tab url";
    107     return L"chrome://newtab";
    108   }
    109   base::string16 dummy_command_line(L"dummy.exe ");
    110   dummy_command_line.append(launch_args);
    111   CommandLine command_line = CommandLine::FromString(dummy_command_line);
    112   CommandLine::StringVector args = command_line.GetArgs();
    113   if (args.size() > 0)
    114     return args[0];
    115 
    116   return base::string16();
    117 }
    118 
    119 void ChromeUrlLaunchHandler::HandleLaunch(
    120     winapp::Activation::ILaunchActivatedEventArgs* args) {
    121   mswrw::HString launch_args;
    122   args->get_Arguments(launch_args.GetAddressOf());
    123   base::string16 actual_launch_args(MakeStdWString(launch_args.Get()));
    124   globals.navigation_url = GetUrlFromLaunchArgs(actual_launch_args);
    125   DVLOG(1) << __FUNCTION__ << ", launch_args=" << actual_launch_args
    126            << ", url=" << globals.navigation_url
    127            << ", is_initial_activation=" << globals.is_initial_activation;
    128 
    129   // If this is the initial launch then we wait for Chrome to initiate the
    130   // navigation. In all other cases navigate right away.
    131   if (!globals.is_initial_activation)
    132     InitiateNavigationOrSearchRequest(globals.navigation_url.c_str(), 0);
    133 }
    134 
    135 void ChromeUrlLaunchHandler::Activate(
    136     winapp::Activation::IActivatedEventArgs* args) {
    137   winapp::Activation::ActivationKind activation_kind;
    138   CheckHR(args->get_Kind(&activation_kind));
    139 
    140   DVLOG(1) << __FUNCTION__ << ", activation_kind=" << activation_kind;
    141 
    142   if (globals.is_initial_activation)
    143     globals.initial_activation_kind = activation_kind;
    144 
    145   if (activation_kind == winapp::Activation::ActivationKind_Launch) {
    146     mswr::ComPtr<winapp::Activation::ILaunchActivatedEventArgs> launch_args;
    147     if (args->QueryInterface(winapp::Activation::IID_ILaunchActivatedEventArgs,
    148                              &launch_args) == S_OK) {
    149       DVLOG(1) << "Activate: ActivationKind_Launch";
    150       HandleLaunch(launch_args.Get());
    151     }
    152   } else if (activation_kind ==
    153              winapp::Activation::ActivationKind_Search) {
    154     mswr::ComPtr<winapp::Activation::ISearchActivatedEventArgs> search_args;
    155     if (args->QueryInterface(winapp::Activation::IID_ISearchActivatedEventArgs,
    156                              &search_args) == S_OK) {
    157       DVLOG(1) << "Activate: ActivationKind_Search";
    158       HandleSearchRequest(search_args.Get());
    159     }
    160   } else if (activation_kind ==
    161              winapp::Activation::ActivationKind_Protocol) {
    162     mswr::ComPtr<winapp::Activation::IProtocolActivatedEventArgs>
    163         protocol_args;
    164     if (args->QueryInterface(
    165             winapp::Activation::IID_IProtocolActivatedEventArgs,
    166             &protocol_args) == S_OK) {
    167       DVLOG(1) << "Activate: ActivationKind_Protocol";
    168       HandleProtocolLaunch(protocol_args.Get());
    169     }
    170   } else {
    171     DVLOG(1) << "Activate: Unhandled mode: " << activation_kind;
    172   }
    173 }
    174 
    175 void ChromeUrlLaunchHandler::InitiateNavigationOrSearchRequest(
    176     const wchar_t* url, const wchar_t* search_string) {
    177   DVLOG(1) << __FUNCTION__;
    178   if (!url && !search_string) {
    179     NOTREACHED();
    180     return;
    181   }
    182 
    183   DVLOG(1) << (url ? url : L"NULL url");
    184   DVLOG(1) << (search_string ? search_string : L"NULL search string");
    185 
    186   if (globals.host_windows.empty()) {
    187     DVLOG(1) << "No chrome windows registered. Ignoring nav request";
    188     return;
    189   }
    190 
    191   // Custom registered message to navigate or search in chrome. WPARAM
    192   // points to the URL and LPARAM contains the search string. They are
    193   // mutually exclusive.
    194   static const UINT navigation_search_message =
    195       RegisterWindowMessage(kMetroNavigationAndSearchMessage);
    196 
    197   if (url) {
    198     VLOG(1) << "Posting url:" << url;
    199     PostMessage(globals.host_windows.front().first, navigation_search_message,
    200                 reinterpret_cast<WPARAM>(url), 0);
    201   } else {
    202     VLOG(1) << "Posting search string:" << search_string;
    203     PostMessage(globals.host_windows.front().first, navigation_search_message,
    204                 0, reinterpret_cast<LPARAM>(search_string));
    205   }
    206 }
    207