Index: chrome_frame/chrome_tab.cc |
=================================================================== |
--- chrome_frame/chrome_tab.cc (revision 0) |
+++ chrome_frame/chrome_tab.cc (revision 0) |
@@ -0,0 +1,308 @@ |
+// Copyright (c) 2009 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. |
+ |
+// chrome_tab.cc : Implementation of DLL Exports. |
+#include "base/at_exit.h" |
+#include "base/command_line.h" |
+#include "base/file_util.h" |
+#include "base/file_version_info.h" |
+#include "base/logging.h" |
+#include "base/path_service.h" |
+#include "base/registry.h" |
+#include "base/string_piece.h" |
+#include "base/string_util.h" |
+#include "base/sys_string_conversions.h" |
+#include "chrome/common/chrome_constants.h" |
+#include "grit/chrome_frame_resources.h" |
+#include "chrome_frame/bho.h" |
+#include "chrome_frame/chrome_frame_automation.h" |
+#include "chrome_frame/chrome_launcher.h" |
+#include "chrome_frame/crash_report.h" |
+#include "chrome_frame/resource.h" |
+#include "chrome_frame/utils.h" |
+ |
+// Include without path to make GYP build see it. |
+#include "chrome_tab.h" // NOLINT |
+ |
+static const wchar_t kBhoRegistryPath[] = |
+ L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer" |
+ L"\\Browser Helper Objects"; |
+ |
+const wchar_t kBhoNoLoadExplorerValue[] = L"NoExplorer"; |
+ |
+class ChromeTabModule |
+ : public AtlPerUserModule<CAtlDllModuleT<ChromeTabModule> > { |
+ public: |
+ typedef AtlPerUserModule<CAtlDllModuleT<ChromeTabModule> > ParentClass; |
+ |
+ DECLARE_LIBID(LIBID_ChromeTabLib) |
+ DECLARE_REGISTRY_APPID_RESOURCEID(IDR_CHROMETAB, |
+ "{FD9B1B31-F4D8-436A-8F4F-D3C2E36733D3}") |
+ |
+ // Override to add our SYSTIME binary value to registry scripts. |
+ // See chrome_frame_activex.rgs for usage. |
+ virtual HRESULT AddCommonRGSReplacements(IRegistrarBase* registrar) throw() { |
+ HRESULT hr = ParentClass::AddCommonRGSReplacements(registrar); |
+ |
+ if (SUCCEEDED(hr)) { |
+ SYSTEMTIME local_time; |
+ ::GetSystemTime(&local_time); |
+ std::string hex(HexEncode(&local_time, sizeof(local_time))); |
+ base::StringPiece sp_hex(hex); |
+ hr = registrar->AddReplacement(L"SYSTIME", |
+ base::SysNativeMBToWide(sp_hex).c_str()); |
+ DCHECK(SUCCEEDED(hr)); |
+ } |
+ |
+ if (SUCCEEDED(hr)) { |
+ std::wstring app_path( |
+ chrome_launcher::GetChromeExecutablePath()); |
+ app_path = file_util::GetDirectoryFromPath(app_path); |
+ hr = registrar->AddReplacement(L"CHROME_APPPATH", app_path.c_str()); |
+ DCHECK(SUCCEEDED(hr)); |
+ } |
+ |
+ if (SUCCEEDED(hr)) { |
+ hr = registrar->AddReplacement(L"CHROME_APPNAME", |
+ chrome::kBrowserProcessExecutableName); |
+ DCHECK(SUCCEEDED(hr)); |
+ |
+ // Fill in VERSION from the VERSIONINFO stored in the DLL's resources. |
+ scoped_ptr<FileVersionInfo> module_version_info( |
+ FileVersionInfo::CreateFileVersionInfoForCurrentModule()); |
+ DCHECK(module_version_info != NULL); |
+ std::wstring file_version(module_version_info->file_version()); |
+ hr = registrar->AddReplacement(L"VERSION", file_version.c_str()); |
+ DCHECK(SUCCEEDED(hr)); |
+ } |
+ |
+ if (SUCCEEDED(hr)) { |
+ // Add the directory of chrome_launcher.exe. This will be the same |
+ // as the directory for the current DLL. |
+ std::wstring module_dir; |
+ FilePath module_path; |
+ if (PathService::Get(base::FILE_MODULE, &module_path)) { |
+ module_dir = module_path.DirName().ToWStringHack(); |
+ } else { |
+ NOTREACHED(); |
+ } |
+ hr = registrar->AddReplacement(L"CHROME_LAUNCHER_APPPATH", |
+ module_dir.c_str()); |
+ DCHECK(SUCCEEDED(hr)); |
+ } |
+ |
+ if (SUCCEEDED(hr)) { |
+ // Add the filename of chrome_launcher.exe |
+ hr = registrar->AddReplacement(L"CHROME_LAUNCHER_APPNAME", |
+ chrome_launcher::kLauncherExeBaseName); |
+ DCHECK(SUCCEEDED(hr)); |
+ } |
+ |
+ return hr; |
+ } |
+}; |
+ |
+ChromeTabModule _AtlModule; |
+ |
+base::AtExitManager* g_exit_manager = NULL; |
+ |
+// DLL Entry Point |
+extern "C" BOOL WINAPI DllMain(HINSTANCE instance, |
+ DWORD reason, |
+ LPVOID reserved) { |
+ UNREFERENCED_PARAMETER(instance); |
+ if (reason == DLL_PROCESS_ATTACH) { |
+#ifndef NDEBUG |
+ // Silence traces from the ATL registrar to reduce the log noise. |
+ ATL::CTrace::s_trace.ChangeCategory(atlTraceRegistrar, 0, |
+ ATLTRACESTATUS_DISABLED); |
+#endif |
+ InitializeCrashReporting(false, false); |
+ g_exit_manager = new base::AtExitManager(); |
+ CommandLine::Init(0, NULL); |
+ logging::InitLogging(NULL, logging::LOG_ONLY_TO_SYSTEM_DEBUG_LOG, |
+ logging::LOCK_LOG_FILE, logging::DELETE_OLD_LOG_FILE); |
+ } else if (reason == DLL_PROCESS_DETACH) { |
+ g_patch_helper.UnpatchIfNeeded(); |
+ delete g_exit_manager; |
+ g_exit_manager = NULL; |
+ ShutdownCrashReporting(); |
+ } |
+ return _AtlModule.DllMain(reason, reserved); |
+} |
+ |
+#ifdef _MANAGED |
+#pragma managed(pop) |
+#endif |
+ |
+const wchar_t kPostPlatformUAKey[] = |
+ L"Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\" |
+ L"User Agent\\Post Platform"; |
+const wchar_t kClockUserAgent[] = L"chromeframe"; |
+ |
+// To delete the clock user agent, set value to NULL. |
+HRESULT SetClockUserAgent(const wchar_t* value) { |
+ HRESULT hr; |
+ RegKey ua_key; |
+ if (ua_key.Create(HKEY_CURRENT_USER, kPostPlatformUAKey, KEY_WRITE)) { |
+ if (value) { |
+ ua_key.WriteValue(kClockUserAgent, value); |
+ } else { |
+ ua_key.DeleteValue(kClockUserAgent); |
+ } |
+ hr = S_OK; |
+ } else { |
+ DLOG(ERROR) << __FUNCTION__ << ": " << kPostPlatformUAKey; |
+ hr = E_UNEXPECTED; |
+ } |
+ |
+ return hr; |
+} |
+ |
+HRESULT RefreshElevationPolicy() { |
+ const wchar_t kIEFrameDll[] = L"ieframe.dll"; |
+ const char kIERefreshPolicy[] = "IERefreshElevationPolicy"; |
+ HRESULT hr = E_NOTIMPL; |
+ HMODULE ieframe_module = LoadLibrary(kIEFrameDll); |
+ if (ieframe_module) { |
+ typedef HRESULT (__stdcall *IERefreshPolicy)(); |
+ IERefreshPolicy ie_refresh_policy = reinterpret_cast<IERefreshPolicy>( |
+ GetProcAddress(ieframe_module, kIERefreshPolicy)); |
+ |
+ if (ie_refresh_policy) { |
+ hr = ie_refresh_policy(); |
+ } else { |
+ hr = HRESULT_FROM_WIN32(GetLastError()); |
+ } |
+ |
+ FreeLibrary(ieframe_module); |
+ } else { |
+ hr = HRESULT_FROM_WIN32(GetLastError()); |
+ } |
+ |
+ return hr; |
+} |
+ |
+HRESULT RegisterChromeTabBHO() { |
+ RegKey ie_bho_key; |
+ if (!ie_bho_key.Create(HKEY_LOCAL_MACHINE, kBhoRegistryPath, |
+ KEY_CREATE_SUB_KEY)) { |
+ DLOG(WARNING) << "Failed to open registry key " |
+ << kBhoRegistryPath |
+ << " for write"; |
+ return E_FAIL; |
+ } |
+ |
+ wchar_t bho_class_id_as_string[MAX_PATH] = {0}; |
+ StringFromGUID2(CLSID_ChromeFrameBHO, bho_class_id_as_string, |
+ arraysize(bho_class_id_as_string)); |
+ |
+ if (!ie_bho_key.CreateKey(bho_class_id_as_string, KEY_READ | KEY_WRITE)) { |
+ DLOG(WARNING) << "Failed to create bho registry key under " |
+ << kBhoRegistryPath |
+ << " for write"; |
+ return E_FAIL; |
+ } |
+ |
+ ie_bho_key.WriteValue(kBhoNoLoadExplorerValue, 1); |
+ DLOG(INFO) << "Registered ChromeTab BHO"; |
+ |
+ SetClockUserAgent(L"1"); |
+ RefreshElevationPolicy(); |
+ return S_OK; |
+} |
+ |
+HRESULT UnregisterChromeTabBHO() { |
+ SetClockUserAgent(NULL); |
+ |
+ RegKey ie_bho_key; |
+ if (!ie_bho_key.Open(HKEY_LOCAL_MACHINE, kBhoRegistryPath, |
+ KEY_READ | KEY_WRITE)) { |
+ DLOG(WARNING) << "Failed to open registry key " |
+ << kBhoRegistryPath |
+ << " for write."; |
+ return E_FAIL; |
+ } |
+ |
+ wchar_t bho_class_id_as_string[MAX_PATH] = {0}; |
+ StringFromGUID2(CLSID_ChromeFrameBHO, bho_class_id_as_string, |
+ arraysize(bho_class_id_as_string)); |
+ |
+ if (!ie_bho_key.DeleteKey(bho_class_id_as_string)) { |
+ DLOG(WARNING) << "Failed to delete bho registry key " |
+ << bho_class_id_as_string |
+ << " under " |
+ << kBhoRegistryPath; |
+ return E_FAIL; |
+ } |
+ |
+ DLOG(INFO) << "Unregistered ChromeTab BHO"; |
+ return S_OK; |
+} |
+ |
+// Used to determine whether the DLL can be unloaded by OLE |
+STDAPI DllCanUnloadNow() { |
+ return _AtlModule.DllCanUnloadNow(); |
+} |
+ |
+// Returns a class factory to create an object of the requested type |
+STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv) { |
+ if (g_patch_helper.state() == PatchHelper::UNKNOWN) { |
+ g_patch_helper.InitializeAndPatchProtocolsIfNeeded(); |
+ UrlMkSetSessionOption(URLMON_OPTION_USERAGENT_REFRESH, NULL, 0, 0); |
+ } |
+ |
+ return _AtlModule.DllGetClassObject(rclsid, riid, ppv); |
+} |
+ |
+// DllRegisterServer - Adds entries to the system registry |
+STDAPI DllRegisterServer() { |
+ // registers object, typelib and all interfaces in typelib |
+ HRESULT hr = _AtlModule.DllRegisterServer(TRUE); |
+ |
+#ifdef GOOGLE_CHROME_BUILD |
+ // Muck with the Omaha configuration so that we don't get updated by non-CF |
+ // Google Chrome builds. |
+ UtilUpdateOmahaConfig(true); |
+#endif |
+ |
+ if (SUCCEEDED(hr)) { |
+ // Best effort attempt to register the BHO. At this point we silently |
+ // ignore any errors during registration. There are some traces emitted |
+ // to the debug log. |
+ RegisterChromeTabBHO(); |
+ } |
+ |
+ return hr; |
+} |
+ |
+// DllUnregisterServer - Removes entries from the system registry |
+STDAPI DllUnregisterServer() { |
+ HRESULT hr = _AtlModule.DllUnregisterServer(TRUE); |
+ |
+#ifdef GOOGLE_CHROME_BUILD |
+ // Undo any prior mucking with the Omaha config. |
+ UtilUpdateOmahaConfig(false); |
+#endif |
+ |
+ if (SUCCEEDED(hr)) { |
+ // Best effort attempt to unregister the BHO. At this point we silently |
+ // ignore any errors during unregistration. There are some traces emitted |
+ // to the debug log. |
+ UnregisterChromeTabBHO(); |
+ } |
+ return hr; |
+} |
+ |
+STDAPI RegisterNPAPIPlugin() { |
+ HRESULT hr = _AtlModule.UpdateRegistryFromResourceS(IDR_CHROMEFRAME_NPAPI, |
+ TRUE); |
+ return hr; |
+} |
+ |
+STDAPI UnregisterNPAPIPlugin() { |
+ HRESULT hr = _AtlModule.UpdateRegistryFromResourceS(IDR_CHROMEFRAME_NPAPI, |
+ FALSE); |
+ return hr; |
+} |