| OLD | NEW |
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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 | 4 |
| 5 // chrome_tab.cc : Implementation of DLL Exports. | 5 // chrome_tab.cc : Implementation of DLL Exports. |
| 6 | 6 |
| 7 // Include without path to make GYP build see it. | 7 // Include without path to make GYP build see it. |
| 8 #include "chrome_tab.h" // NOLINT | 8 #include "chrome_tab.h" // NOLINT |
| 9 | 9 |
| 10 #include <atlsecurity.h> | 10 #include <atlsecurity.h> |
| 11 | 11 |
| 12 #include "base/at_exit.h" | 12 #include "base/at_exit.h" |
| 13 #include "base/command_line.h" | 13 #include "base/command_line.h" |
| 14 #include "base/file_util.h" | 14 #include "base/file_util.h" |
| 15 #include "base/file_version_info.h" | 15 #include "base/file_version_info.h" |
| 16 #include "base/lock.h" | 16 #include "base/lock.h" |
| 17 #include "base/logging.h" | 17 #include "base/logging.h" |
| 18 #include "base/logging_win.h" | 18 #include "base/logging_win.h" |
| 19 #include "base/path_service.h" | 19 #include "base/path_service.h" |
| 20 #include "base/registry.h" | 20 #include "base/registry.h" |
| 21 #include "base/string_piece.h" | 21 #include "base/string_piece.h" |
| 22 #include "base/string_util.h" | 22 #include "base/string_util.h" |
| 23 #include "base/sys_string_conversions.h" | 23 #include "base/sys_string_conversions.h" |
| 24 #include "base/win_util.h" | 24 #include "base/win_util.h" |
| 25 #include "chrome/common/chrome_constants.h" | 25 #include "chrome/common/chrome_constants.h" |
| 26 #include "chrome/common/chrome_switches.h" |
| 27 #include "chrome/installer/util/google_update_settings.h" |
| 26 #include "grit/chrome_frame_resources.h" | 28 #include "grit/chrome_frame_resources.h" |
| 27 #include "chrome_frame/bho.h" | 29 #include "chrome_frame/bho.h" |
| 28 #include "chrome_frame/chrome_active_document.h" | 30 #include "chrome_frame/chrome_active_document.h" |
| 29 #include "chrome_frame/chrome_frame_activex.h" | 31 #include "chrome_frame/chrome_frame_activex.h" |
| 30 #include "chrome_frame/chrome_frame_automation.h" | 32 #include "chrome_frame/chrome_frame_automation.h" |
| 31 #include "chrome_frame/exception_barrier.h" | 33 #include "chrome_frame/exception_barrier.h" |
| 32 #include "chrome_frame/chrome_frame_reporting.h" | 34 #include "chrome_frame/chrome_frame_reporting.h" |
| 33 #include "chrome_frame/chrome_launcher_utils.h" | 35 #include "chrome_frame/chrome_launcher_utils.h" |
| 34 #include "chrome_frame/chrome_protocol.h" | 36 #include "chrome_frame/chrome_protocol.h" |
| 35 #include "chrome_frame/module_utils.h" | 37 #include "chrome_frame/module_utils.h" |
| (...skipping 17 matching lines...) Expand all Loading... |
| 53 static const wchar_t kBhoRegistryPath[] = | 55 static const wchar_t kBhoRegistryPath[] = |
| 54 L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer" | 56 L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer" |
| 55 L"\\Browser Helper Objects"; | 57 L"\\Browser Helper Objects"; |
| 56 | 58 |
| 57 const wchar_t kInternetSettings[] = | 59 const wchar_t kInternetSettings[] = |
| 58 L"Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings"; | 60 L"Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings"; |
| 59 | 61 |
| 60 const wchar_t kProtocolHandlers[] = | 62 const wchar_t kProtocolHandlers[] = |
| 61 L"Software\\Classes\\Protocols\\Handler"; | 63 L"Software\\Classes\\Protocols\\Handler"; |
| 62 | 64 |
| 65 const wchar_t kRunOnce[] = |
| 66 L"Software\\Microsoft\\Windows\\CurrentVersion\\RunOnce"; |
| 67 |
| 63 const wchar_t kBhoNoLoadExplorerValue[] = L"NoExplorer"; | 68 const wchar_t kBhoNoLoadExplorerValue[] = L"NoExplorer"; |
| 64 | 69 |
| 65 // {0562BFC3-2550-45b4-BD8E-A310583D3A6F} | 70 // {0562BFC3-2550-45b4-BD8E-A310583D3A6F} |
| 66 static const GUID kChromeFrameProvider = | 71 static const GUID kChromeFrameProvider = |
| 67 { 0x562bfc3, 0x2550, 0x45b4, | 72 { 0x562bfc3, 0x2550, 0x45b4, |
| 68 { 0xbd, 0x8e, 0xa3, 0x10, 0x58, 0x3d, 0x3a, 0x6f } }; | 73 { 0xbd, 0x8e, 0xa3, 0x10, 0x58, 0x3d, 0x3a, 0x6f } }; |
| 69 | 74 |
| 70 // Object entries go here instead of with each object, so that we can move | 75 // Object entries go here instead of with each object, so that we can move |
| 71 // the objects to a lib. Also reduces magic. | 76 // the objects to a lib. Also reduces magic. |
| 72 OBJECT_ENTRY_AUTO(CLSID_ChromeFrameBHO, Bho) | 77 OBJECT_ENTRY_AUTO(CLSID_ChromeFrameBHO, Bho) |
| (...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 199 g_exit_manager = NULL; | 204 g_exit_manager = NULL; |
| 200 ShutdownCrashReporting(); | 205 ShutdownCrashReporting(); |
| 201 } | 206 } |
| 202 return _AtlModule.DllMain(reason, reserved); | 207 return _AtlModule.DllMain(reason, reserved); |
| 203 } | 208 } |
| 204 | 209 |
| 205 #ifdef _MANAGED | 210 #ifdef _MANAGED |
| 206 #pragma managed(pop) | 211 #pragma managed(pop) |
| 207 #endif | 212 #endif |
| 208 | 213 |
| 209 const wchar_t kPostPlatformUAKey[] = | |
| 210 L"Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\" | |
| 211 L"User Agent\\Post Platform"; | |
| 212 const wchar_t kClockUserAgent[] = L"chromeframe"; | |
| 213 | |
| 214 // To delete the clock user agent, set value to NULL. | |
| 215 // TODO(tommi): Remove this method when it's no longer used. | |
| 216 HRESULT SetClockUserAgent(const wchar_t* value) { | |
| 217 HRESULT hr; | |
| 218 RegKey ua_key; | |
| 219 if (ua_key.Create(HKEY_LOCAL_MACHINE, kPostPlatformUAKey, KEY_WRITE)) { | |
| 220 if (value) { | |
| 221 ua_key.WriteValue(kClockUserAgent, value); | |
| 222 } else { | |
| 223 ua_key.DeleteValue(kClockUserAgent); | |
| 224 } | |
| 225 hr = S_OK; | |
| 226 } else { | |
| 227 DLOG(ERROR) << __FUNCTION__ << ": " << kPostPlatformUAKey; | |
| 228 hr = E_UNEXPECTED; | |
| 229 } | |
| 230 | |
| 231 return hr; | |
| 232 } | |
| 233 | |
| 234 HRESULT RefreshElevationPolicy() { | 214 HRESULT RefreshElevationPolicy() { |
| 235 const wchar_t kIEFrameDll[] = L"ieframe.dll"; | 215 const wchar_t kIEFrameDll[] = L"ieframe.dll"; |
| 236 const char kIERefreshPolicy[] = "IERefreshElevationPolicy"; | 216 const char kIERefreshPolicy[] = "IERefreshElevationPolicy"; |
| 237 HRESULT hr = E_NOTIMPL; | 217 HRESULT hr = E_NOTIMPL; |
| 238 | 218 |
| 239 // Stick an SEH in the chain to prevent the VEH from picking up on first | 219 // Stick an SEH in the chain to prevent the VEH from picking up on first |
| 240 // chance exceptions caused by loading ieframe.dll. Use the vanilla | 220 // chance exceptions caused by loading ieframe.dll. Use the vanilla |
| 241 // ExceptionBarrier to report any exceptions that do make their way to us | 221 // ExceptionBarrier to report any exceptions that do make their way to us |
| 242 // though. | 222 // though. |
| 243 ExceptionBarrier barrier; | 223 ExceptionBarrier barrier; |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 285 | 265 |
| 286 ie_bho_key.WriteValue(kBhoNoLoadExplorerValue, 1); | 266 ie_bho_key.WriteValue(kBhoNoLoadExplorerValue, 1); |
| 287 DLOG(INFO) << "Registered ChromeTab BHO"; | 267 DLOG(INFO) << "Registered ChromeTab BHO"; |
| 288 | 268 |
| 289 // We now add the chromeframe user agent at runtime. | 269 // We now add the chromeframe user agent at runtime. |
| 290 RefreshElevationPolicy(); | 270 RefreshElevationPolicy(); |
| 291 return S_OK; | 271 return S_OK; |
| 292 } | 272 } |
| 293 | 273 |
| 294 HRESULT UnregisterChromeTabBHO() { | 274 HRESULT UnregisterChromeTabBHO() { |
| 295 // TODO(tommi): remove this in future versions. | |
| 296 SetClockUserAgent(NULL); | |
| 297 | |
| 298 RegKey ie_bho_key; | 275 RegKey ie_bho_key; |
| 299 if (!ie_bho_key.Open(HKEY_LOCAL_MACHINE, kBhoRegistryPath, | 276 if (!ie_bho_key.Open(HKEY_LOCAL_MACHINE, kBhoRegistryPath, |
| 300 KEY_READ | KEY_WRITE)) { | 277 KEY_READ | KEY_WRITE)) { |
| 301 DLOG(WARNING) << "Failed to open registry key " | 278 DLOG(WARNING) << "Failed to open registry key " |
| 302 << kBhoRegistryPath | 279 << kBhoRegistryPath |
| 303 << " for write."; | 280 << " for write."; |
| 304 return E_FAIL; | 281 return E_FAIL; |
| 305 } | 282 } |
| 306 | 283 |
| 307 wchar_t bho_class_id_as_string[MAX_PATH] = {0}; | 284 wchar_t bho_class_id_as_string[MAX_PATH] = {0}; |
| 308 StringFromGUID2(CLSID_ChromeFrameBHO, bho_class_id_as_string, | 285 StringFromGUID2(CLSID_ChromeFrameBHO, bho_class_id_as_string, |
| 309 arraysize(bho_class_id_as_string)); | 286 arraysize(bho_class_id_as_string)); |
| 310 | 287 |
| 311 if (!ie_bho_key.DeleteKey(bho_class_id_as_string)) { | 288 if (!ie_bho_key.DeleteKey(bho_class_id_as_string)) { |
| 312 DLOG(WARNING) << "Failed to delete bho registry key " | 289 DLOG(WARNING) << "Failed to delete bho registry key " |
| 313 << bho_class_id_as_string | 290 << bho_class_id_as_string |
| 314 << " under " | 291 << " under " |
| 315 << kBhoRegistryPath; | 292 << kBhoRegistryPath; |
| 316 return E_FAIL; | 293 return E_FAIL; |
| 317 } | 294 } |
| 318 | 295 |
| 319 DLOG(INFO) << "Unregistered ChromeTab BHO"; | 296 DLOG(INFO) << "Unregistered ChromeTab BHO"; |
| 320 return S_OK; | 297 return S_OK; |
| 321 } | 298 } |
| 322 | 299 |
| 323 HRESULT CleanupCFProtocol() { | 300 // Experimental boot prefetch optimization for Chrome Frame |
| 324 RegKey protocol_handlers_key; | 301 // |
| 325 if (protocol_handlers_key.Open(HKEY_LOCAL_MACHINE, kProtocolHandlers, | 302 // If chrome is warmed up during a single reboot, it gets paged |
| 326 KEY_READ | KEY_WRITE)) { | 303 // in for subsequent reboots and the cold startup times essentially |
| 327 RegKey cf_protocol_key; | 304 // look like warm times thereafter! The 'warm up' is done by |
| 328 if (cf_protocol_key.Open(protocol_handlers_key.Handle(), L"cf", | 305 // setting up a 'RunOnce' key during DLLRegisterServer of |
| 329 KEY_QUERY_VALUE)) { | 306 // npchrome_frame.dll. |
| 330 std::wstring protocol_clsid_string; | 307 // |
| 331 if (cf_protocol_key.ReadValue(L"CLSID", &protocol_clsid_string)) { | 308 // This works because chrome prefetch becomes part of boot |
| 332 CLSID protocol_clsid = {0}; | 309 // prefetch file ntosboot-b00dfaad.pf and paged in on subsequent |
| 333 IIDFromString(protocol_clsid_string.c_str(), &protocol_clsid); | 310 // reboots. As long as the sytem does not undergo significant |
| 334 if (IsEqualGUID(protocol_clsid, CLSID_ChromeProtocol)) | 311 // memory pressure those pages remain in memory and we get pretty |
| 335 protocol_handlers_key.DeleteKey(L"cf"); | 312 // amazing startup times, down to about 300 ms from 1200 ms |
| 336 } | 313 // |
| 337 } | 314 // The downside is: |
| 315 // - Whether chrome frame is used or not, there's a read penalty |
| 316 // (1200-300 =) 900 ms for every boot. |
| 317 // - Heavy system memory usage after reboot will nullify the benefits |
| 318 // but the user will still pay the cost. |
| 319 // - Overall the time saved will always be less than total time spent |
| 320 // paging in chrome |
| 321 // - We are not sure when the chrome 'warm up' will age out from the |
| 322 // boot prefetch file. |
| 323 // |
| 324 // The idea here is to try this out on chrome frame dev channel |
| 325 // and see if it produces a significant drift in startup numbers. |
| 326 HRESULT SetupRunOnce() { |
| 327 if (win_util::GetWinVersion() >= win_util::WINVERSION_VISTA) |
| 328 return S_OK; |
| 329 |
| 330 std::wstring channel_name; |
| 331 if (!GoogleUpdateSettings::GetChromeChannel(true, &channel_name) || |
| 332 (0 != lstrcmpiW(L"dev", channel_name.c_str()))) { |
| 333 return S_OK; |
| 334 } |
| 335 |
| 336 RegKey run_once; |
| 337 if (run_once.Create(HKEY_CURRENT_USER, kRunOnce, KEY_READ | KEY_WRITE)) { |
| 338 CommandLine run_once_command(chrome_launcher::GetChromeExecutablePath()); |
| 339 run_once_command.AppendSwitchWithValue( |
| 340 switches::kAutomationClientChannelID, L"0"); |
| 341 run_once_command.AppendSwitch(switches::kChromeFrame); |
| 342 run_once.WriteValue(L"A", run_once_command.command_line_string().c_str()); |
| 338 } | 343 } |
| 339 | 344 |
| 340 return S_OK; | 345 return S_OK; |
| 341 } | 346 } |
| 342 | 347 |
| 343 // Used to determine whether the DLL can be unloaded by OLE | 348 // Used to determine whether the DLL can be unloaded by OLE |
| 344 STDAPI DllCanUnloadNow() { | 349 STDAPI DllCanUnloadNow() { |
| 345 return _AtlModule.DllCanUnloadNow(); | 350 return _AtlModule.DllCanUnloadNow(); |
| 346 } | 351 } |
| 347 | 352 |
| (...skipping 14 matching lines...) Expand all Loading... |
| 362 // registers object, typelib and all interfaces in typelib | 367 // registers object, typelib and all interfaces in typelib |
| 363 HRESULT hr = _AtlModule.DllRegisterServer(TRUE); | 368 HRESULT hr = _AtlModule.DllRegisterServer(TRUE); |
| 364 | 369 |
| 365 if (SUCCEEDED(hr)) { | 370 if (SUCCEEDED(hr)) { |
| 366 // Best effort attempt to register the BHO. At this point we silently | 371 // Best effort attempt to register the BHO. At this point we silently |
| 367 // ignore any errors during registration. There are some traces emitted | 372 // ignore any errors during registration. There are some traces emitted |
| 368 // to the debug log. | 373 // to the debug log. |
| 369 RegisterChromeTabBHO(); | 374 RegisterChromeTabBHO(); |
| 370 if (!RegisterSecuredMimeHandler(true)) | 375 if (!RegisterSecuredMimeHandler(true)) |
| 371 hr = E_FAIL; | 376 hr = E_FAIL; |
| 377 SetupRunOnce(); |
| 372 } | 378 } |
| 373 | 379 |
| 374 if (UtilIsPersistentNPAPIMarkerSet()) { | 380 if (UtilIsPersistentNPAPIMarkerSet()) { |
| 375 hr = _AtlModule.UpdateRegistryFromResourceS(IDR_CHROMEFRAME_NPAPI, TRUE); | 381 hr = _AtlModule.UpdateRegistryFromResourceS(IDR_CHROMEFRAME_NPAPI, TRUE); |
| 376 } | 382 } |
| 377 | 383 |
| 378 return hr; | 384 return hr; |
| 379 } | 385 } |
| 380 | 386 |
| 381 // DllUnregisterServer - Removes entries from the system registry | 387 // DllUnregisterServer - Removes entries from the system registry |
| 382 STDAPI DllUnregisterServer() { | 388 STDAPI DllUnregisterServer() { |
| 383 HRESULT hr = _AtlModule.DllUnregisterServer(TRUE); | 389 HRESULT hr = _AtlModule.DllUnregisterServer(TRUE); |
| 384 | 390 |
| 385 if (SUCCEEDED(hr)) { | 391 if (SUCCEEDED(hr)) { |
| 386 // Best effort attempt to unregister the BHO. At this point we silently | 392 // Best effort attempt to unregister the BHO. At this point we silently |
| 387 // ignore any errors during unregistration. There are some traces emitted | 393 // ignore any errors during unregistration. There are some traces emitted |
| 388 // to the debug log. | 394 // to the debug log. |
| 389 UnregisterChromeTabBHO(); | 395 UnregisterChromeTabBHO(); |
| 390 if (!RegisterSecuredMimeHandler(false)) | 396 if (!RegisterSecuredMimeHandler(false)) |
| 391 hr = E_FAIL; | 397 hr = E_FAIL; |
| 392 } | 398 } |
| 393 | 399 |
| 394 if (UtilIsNPAPIPluginRegistered()) { | 400 if (UtilIsNPAPIPluginRegistered()) { |
| 395 hr = _AtlModule.UpdateRegistryFromResourceS(IDR_CHROMEFRAME_NPAPI, FALSE); | 401 hr = _AtlModule.UpdateRegistryFromResourceS(IDR_CHROMEFRAME_NPAPI, FALSE); |
| 396 } | 402 } |
| 397 | 403 |
| 398 // TODO(joshia): Remove after 2 refresh releases | |
| 399 CleanupCFProtocol(); | |
| 400 return hr; | 404 return hr; |
| 401 } | 405 } |
| 402 | 406 |
| 403 // Registers the NPAPI plugin and sets the persistent marker that tells us | 407 // Registers the NPAPI plugin and sets the persistent marker that tells us |
| 404 // to re-register it through updates. | 408 // to re-register it through updates. |
| 405 STDAPI RegisterNPAPIPlugin() { | 409 STDAPI RegisterNPAPIPlugin() { |
| 406 HRESULT hr = _AtlModule.UpdateRegistryFromResourceS(IDR_CHROMEFRAME_NPAPI, | 410 HRESULT hr = _AtlModule.UpdateRegistryFromResourceS(IDR_CHROMEFRAME_NPAPI, |
| 407 TRUE); | 411 TRUE); |
| 408 if (SUCCEEDED(hr)) { | 412 if (SUCCEEDED(hr)) { |
| 409 if (!UtilChangePersistentNPAPIMarker(true)) { | 413 if (!UtilChangePersistentNPAPIMarker(true)) { |
| (...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 595 sd.GetDacl(&new_dacl); | 599 sd.GetDacl(&new_dacl); |
| 596 new_dacl.AddAllowedAce(token_.GetUser(), GENERIC_WRITE | GENERIC_READ); | 600 new_dacl.AddAllowedAce(token_.GetUser(), GENERIC_WRITE | GENERIC_READ); |
| 597 if (AtlSetDacl(object_name.c_str(), SE_REGISTRY_KEY, new_dacl)) { | 601 if (AtlSetDacl(object_name.c_str(), SE_REGISTRY_KEY, new_dacl)) { |
| 598 result = SetOrDeleteMimeHandlerKey(enable); | 602 result = SetOrDeleteMimeHandlerKey(enable); |
| 599 } | 603 } |
| 600 } | 604 } |
| 601 | 605 |
| 602 backup.RestoreSecurity(object_name.c_str()); | 606 backup.RestoreSecurity(object_name.c_str()); |
| 603 return result; | 607 return result; |
| 604 } | 608 } |
| OLD | NEW |