OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 // Implementation of the CommandExecuteImpl class which implements the | 4 // Implementation of the CommandExecuteImpl class which implements the |
5 // IExecuteCommand and related interfaces for handling ShellExecute based | 5 // IExecuteCommand and related interfaces for handling ShellExecute based |
6 // launches of the Chrome browser. | 6 // launches of the Chrome browser. |
7 | 7 |
8 #include "win8/delegate_execute/command_execute_impl.h" | 8 #include "win8/delegate_execute/command_execute_impl.h" |
9 | 9 |
10 #include <shlguid.h> | 10 #include <shlguid.h> |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
109 | 109 |
110 // CommandExecuteImpl is resposible for activating chrome in Windows 8. The | 110 // CommandExecuteImpl is resposible for activating chrome in Windows 8. The |
111 // flow is complicated and this tries to highlight the important events. | 111 // flow is complicated and this tries to highlight the important events. |
112 // The current approach is to have a single instance of chrome either | 112 // The current approach is to have a single instance of chrome either |
113 // running in desktop or metro mode. If there is no current instance then | 113 // running in desktop or metro mode. If there is no current instance then |
114 // the desktop shortcut launches desktop chrome and the metro tile or search | 114 // the desktop shortcut launches desktop chrome and the metro tile or search |
115 // charm launches metro chrome. | 115 // charm launches metro chrome. |
116 // If chrome is running then focus/activation is given to the existing one | 116 // If chrome is running then focus/activation is given to the existing one |
117 // regarless of what launch point the user used. | 117 // regarless of what launch point the user used. |
118 // | 118 // |
119 // The general flow when chrome is the default browser is as follows: | 119 // The general flow for activation is as follows: |
120 // | 120 // |
121 // 1- User interacts with launch point (icon, tile, search, shellexec, etc) | 121 // 1- User interacts with launch point (icon, tile, search, shellexec, etc) |
122 // 2- Windows finds the appid for launch item and resolves it to chrome | 122 // 2- Windows finds the appid for launch item and resolves it to chrome |
123 // 3- Windows activates CommandExecuteImpl inside a surrogate process | 123 // 3- Windows activates CommandExecuteImpl inside a surrogate process |
124 // 4- Windows calls the following sequence of entry points: | 124 // 4- Windows calls the following sequence of entry points: |
125 // CommandExecuteImpl::SetShowWindow | 125 // CommandExecuteImpl::SetShowWindow |
126 // CommandExecuteImpl::SetPosition | 126 // CommandExecuteImpl::SetPosition |
127 // CommandExecuteImpl::SetDirectory | 127 // CommandExecuteImpl::SetDirectory |
128 // CommandExecuteImpl::SetParameter | 128 // CommandExecuteImpl::SetParameter |
129 // CommandExecuteImpl::SetNoShowUI | 129 // CommandExecuteImpl::SetNoShowUI |
130 // CommandExecuteImpl::SetSelection | 130 // CommandExecuteImpl::SetSelection |
131 // CommandExecuteImpl::Initialize | 131 // CommandExecuteImpl::Initialize |
132 // Up to this point the code basically just gathers values passed in, like | 132 // Up to this point the code basically just gathers values passed in, like |
133 // the launch scheme (or url) and the activation verb. | 133 // the launch scheme (or url) and the activation verb. |
134 // 5- Windows calls CommandExecuteImpl::Getvalue() | 134 // 5- Windows calls CommandExecuteImpl::Getvalue() |
135 // Here we need to return AHE_IMMERSIVE or AHE_DESKTOP. That depends on: | 135 // Here we need to return AHE_IMMERSIVE or AHE_DESKTOP. That depends on: |
136 // a) if run in high-integrity return AHE_DESKTOP | 136 // a) if run in high-integrity return AHE_DESKTOP. |
137 // b) else we return what GetLaunchMode() tells us, which is: | 137 // b) else we return what GetLaunchMode() tells us, which is: |
138 // i) if the command line --force-xxx is present return that | 138 // i) if chrome is not the default browser, return AHE_DESKTOP |
139 // ii) if the registry 'launch_mode' exists return that | 139 // ii) if the command line --force-xxx is present return that |
140 // iii) else return AHE_DESKTOP | 140 // iii) if the registry 'launch_mode' exists return that |
| 141 // iv) else return AHE_DESKTOP |
141 // 6- If we returned AHE_IMMERSIVE in step 5 windows might not call us back | 142 // 6- If we returned AHE_IMMERSIVE in step 5 windows might not call us back |
142 // and simply activate chrome in metro by itself, however in some cases | 143 // and simply activate chrome in metro by itself, however in some cases |
143 // it might proceed at step 7. | 144 // it might proceed at step 7. |
144 // As far as we know if we return AHE_DESKTOP then step 7 always happens. | 145 // As far as we know if we return AHE_DESKTOP then step 7 always happens. |
145 // 7- Windows calls CommandExecuteImpl::Execute() | 146 // 7- Windows calls CommandExecuteImpl::Execute() |
146 // Here we call GetLaunchMode() which returns the cached answer | 147 // Here we call GetLaunchMode() which returns the cached answer |
147 // computed at step 5c. which can be: | 148 // computed at step 5c. which can be: |
148 // a) ECHUIM_DESKTOP then we call LaunchDesktopChrome() that calls | 149 // a) ECHUIM_DESKTOP then we call LaunchDesktopChrome() that calls |
149 // ::CreateProcess and we exit at this point even on failure. | 150 // ::CreateProcess and we exit at this point even on failure. |
150 // b) else we call one of the IApplicationActivationManager activation | 151 // b) else we call one of the IApplicationActivationManager activation |
151 // functions depending on the parameters passed in step 4. | 152 // functions depending on the parameters passed in step 4. |
152 // c) If the activation returns E_APPLICATION_NOT_REGISTERED, then we fall | 153 // c) If the activation returns E_APPLICATION_NOT_REGISTERED, then we fall |
153 // back to launching chrome on the desktop via LaunchDestopChrome(). | 154 // back to launching chrome on the desktop via LaunchDestopChrome(). Note |
| 155 // that this case can lead to strange behavior, because at this point we |
| 156 // have pre-launched the browser with --silent-launch --viewer-connect. |
| 157 // E_APPLICATION_NOT_REGISTERED is always returned if Chrome is not the |
| 158 // default browser (this case will have already been checked for by |
| 159 // GetLaunchMode() and AHE_DESKTOP returned), but we don't know if it can |
| 160 // be returned for other reasons. |
154 // | 161 // |
155 // Note that if a command line --force-xxx is present we write that launch mode | 162 // Note that if a command line --force-xxx is present we write that launch mode |
156 // in the registry so next time the logic reaches 5c-ii it will use the same | 163 // in the registry so next time the logic reaches 5c-ii it will use the same |
157 // mode again. | 164 // mode again. |
158 // | 165 // |
159 CommandExecuteImpl::CommandExecuteImpl() | 166 CommandExecuteImpl::CommandExecuteImpl() |
160 : parameters_(CommandLine::NO_PROGRAM), | 167 : parameters_(CommandLine::NO_PROGRAM), |
161 launch_scheme_(INTERNET_SCHEME_DEFAULT), | 168 launch_scheme_(INTERNET_SCHEME_DEFAULT), |
162 integrity_level_(base::INTEGRITY_UNKNOWN) { | 169 integrity_level_(base::INTEGRITY_UNKNOWN) { |
163 memset(&start_info_, 0, sizeof(start_info_)); | 170 memset(&start_info_, 0, sizeof(start_info_)); |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
202 | 209 |
203 STDMETHODIMP CommandExecuteImpl::GetValue(enum AHE_TYPE* pahe) { | 210 STDMETHODIMP CommandExecuteImpl::GetValue(enum AHE_TYPE* pahe) { |
204 if (!GetLaunchScheme(&display_name_, &launch_scheme_)) { | 211 if (!GetLaunchScheme(&display_name_, &launch_scheme_)) { |
205 AtlTrace("Failed to get scheme, E_FAIL\n"); | 212 AtlTrace("Failed to get scheme, E_FAIL\n"); |
206 return E_FAIL; | 213 return E_FAIL; |
207 } | 214 } |
208 | 215 |
209 EC_HOST_UI_MODE mode = GetLaunchMode(); | 216 EC_HOST_UI_MODE mode = GetLaunchMode(); |
210 *pahe = (mode == ECHUIM_DESKTOP) ? AHE_DESKTOP : AHE_IMMERSIVE; | 217 *pahe = (mode == ECHUIM_DESKTOP) ? AHE_DESKTOP : AHE_IMMERSIVE; |
211 | 218 |
| 219 // If we're going to return AHE_IMMERSIVE, then both the browser process and |
| 220 // the metro viewer need to launch and connect before the user can start |
| 221 // browsing. However we must not launch the metro viewer until we get a |
| 222 // call to CommandExecuteImpl::Execute(). If we wait until then to launch |
| 223 // the browser process as well, it will appear laggy while they connect to |
| 224 // each other, so we pre-launch the browser process now. |
212 if (*pahe == AHE_IMMERSIVE && verb_ != win8::kMetroViewerConnectVerb) | 225 if (*pahe == AHE_IMMERSIVE && verb_ != win8::kMetroViewerConnectVerb) |
213 LaunchChromeBrowserProcess(); | 226 LaunchChromeBrowserProcess(); |
214 return S_OK; | 227 return S_OK; |
215 } | 228 } |
216 | 229 |
217 STDMETHODIMP CommandExecuteImpl::Execute() { | 230 STDMETHODIMP CommandExecuteImpl::Execute() { |
218 AtlTrace("In %hs\n", __FUNCTION__); | 231 AtlTrace("In %hs\n", __FUNCTION__); |
219 | 232 |
220 if (integrity_level_ == base::HIGH_INTEGRITY) | 233 if (integrity_level_ == base::HIGH_INTEGRITY) |
221 return LaunchDesktopChrome(); | 234 return LaunchDesktopChrome(); |
(...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
408 if (launch_mode_determined) | 421 if (launch_mode_determined) |
409 return launch_mode; | 422 return launch_mode; |
410 | 423 |
411 if (integrity_level_ == base::HIGH_INTEGRITY) { | 424 if (integrity_level_ == base::HIGH_INTEGRITY) { |
412 // Metro mode apps don't work in high integrity mode. | 425 // Metro mode apps don't work in high integrity mode. |
413 AtlTrace("High integrity: launching in desktop mode\n"); | 426 AtlTrace("High integrity: launching in desktop mode\n"); |
414 launch_mode = ECHUIM_DESKTOP; | 427 launch_mode = ECHUIM_DESKTOP; |
415 launch_mode_determined = true; | 428 launch_mode_determined = true; |
416 return launch_mode; | 429 return launch_mode; |
417 } | 430 } |
| 431 |
| 432 base::FilePath chrome_exe; |
| 433 if (!FindChromeExe(&chrome_exe) || |
| 434 ShellUtil::GetChromeDefaultStateFromPath(chrome_exe) != |
| 435 ShellUtil::DefaultState::IS_DEFAULT) { |
| 436 AtlTrace("Chrome is not default: launching in desktop mode\n"); |
| 437 launch_mode = ECHUIM_DESKTOP; |
| 438 launch_mode_determined = true; |
| 439 return launch_mode; |
| 440 } |
| 441 |
418 if (GetAsyncKeyState(VK_SHIFT) && GetAsyncKeyState(VK_F11)) { | 442 if (GetAsyncKeyState(VK_SHIFT) && GetAsyncKeyState(VK_F11)) { |
419 AtlTrace("Hotkey: launching in immersive mode\n"); | 443 AtlTrace("Hotkey: launching in immersive mode\n"); |
420 launch_mode = ECHUIM_IMMERSIVE; | 444 launch_mode = ECHUIM_IMMERSIVE; |
421 launch_mode_determined = true; | 445 launch_mode_determined = true; |
422 return launch_mode; | 446 return launch_mode; |
423 } | 447 } |
424 | 448 |
425 // From here on, if we can, we will write the outcome | 449 // From here on, if we can, we will write the outcome |
426 // of this function to the registry. | 450 // of this function to the registry. |
427 if (parameters_.HasSwitch(switches::kForceImmersive)) { | 451 if (parameters_.HasSwitch(switches::kForceImmersive)) { |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
468 AtlTrace("Invalid registry launch mode value %u\n", reg_value); | 492 AtlTrace("Invalid registry launch mode value %u\n", reg_value); |
469 launch_mode = ECHUIM_DESKTOP; | 493 launch_mode = ECHUIM_DESKTOP; |
470 } else { | 494 } else { |
471 launch_mode = static_cast<EC_HOST_UI_MODE>(reg_value); | 495 launch_mode = static_cast<EC_HOST_UI_MODE>(reg_value); |
472 AtlTrace("Launch mode forced by registry to %s\n", modes[launch_mode]); | 496 AtlTrace("Launch mode forced by registry to %s\n", modes[launch_mode]); |
473 } | 497 } |
474 | 498 |
475 launch_mode_determined = true; | 499 launch_mode_determined = true; |
476 return launch_mode; | 500 return launch_mode; |
477 } | 501 } |
OLD | NEW |