Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(6976)

Unified Diff: chrome_frame/chrome_tab.cc

Issue 7824010: Make Chrome Frame registration and unregistration more robust. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: '' Created 9 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chrome_frame/chrome_tab.cc
===================================================================
--- chrome_frame/chrome_tab.cc (revision 98956)
+++ chrome_frame/chrome_tab.cc (working copy)
@@ -15,6 +15,7 @@
#include "base/file_version_info.h"
#include "base/logging.h"
#include "base/logging_win.h"
+#include "base/memory/scoped_vector.h"
#include "base/path_service.h"
#include "base/string_number_conversions.h"
#include "base/string_piece.h"
@@ -490,110 +491,303 @@
ALL = 0xFFFF
};
-STDAPI CustomRegistration(UINT reg_flags, BOOL reg, bool is_system) {
- UINT flags = reg_flags;
+class CustomRegistrationHelper {
grt (UTC plus 2) 2011/09/02 19:01:35 Looks like it wouldn't be hard to make this a pure
grt (UTC plus 2) 2011/09/02 19:01:35 On second thought, I'd be sorely tempted to simpli
robertshield 2011/09/03 05:36:21 Done.
robertshield 2011/09/03 05:36:21 This is a much nicer approach, changed as you sugg
+ public:
+ CustomRegistrationHelper(UINT reg_flags, bool is_system)
grt (UTC plus 2) 2011/09/02 19:01:35 i think uint32 is more stylistically appropriate.
robertshield 2011/09/03 05:36:21 Done.
+ : reg_flags_(reg_flags), is_system_(is_system) {
+ }
- if (reg && (flags & (ACTIVEDOC | ACTIVEX)))
- flags |= (TYPELIB | GCF_PROTOCOL);
+ HRESULT Run(bool reg) {
+ return Do(reg);
+ }
- HRESULT hr = S_OK;
+ HRESULT Rollback(bool reg) {
+ return Do(!reg);
+ }
- // Set the flag that gets checked in AddCommonRGSReplacements before doing
- // registration work.
- _AtlModule.do_system_registration_ = is_system;
+ protected:
+ virtual HRESULT Do(bool reg) = 0;
- if ((hr == S_OK) && (flags & ACTIVEDOC)) {
- // Don't fail to unregister if we can't undo the secure mime
- // handler registration. This was observed getting hit during
- // uninstallation.
- if (!RegisterSecuredMimeHandler(reg ? true : false, is_system) && reg)
- return E_FAIL;
- hr = ChromeActiveDocument::UpdateRegistry(reg);
+ UINT reg_flags_;
+ bool is_system_;
+};
+
+class CRHSecuredMimeHandler : public CustomRegistrationHelper {
+ public:
+ CRHSecuredMimeHandler(UINT reg_flags, bool is_system)
+ : CustomRegistrationHelper(reg_flags, is_system) {}
+
+ private:
+ HRESULT Do(bool reg) {
grt (UTC plus 2) 2011/09/02 19:01:35 ) OVERRIDE { here and in all other classes.
robertshield 2011/09/03 05:36:21 No longer needed.
+ if (reg_flags_ & ACTIVEDOC) {
+ // Don't fail to unregister if we can't undo the secure mime
grt (UTC plus 2) 2011/09/02 19:01:35 This comment and code are stale; the decision of w
robertshield 2011/09/03 05:36:21 Done.
+ // handler registration. This was observed getting hit during
+ // uninstallation.
+ if (!RegisterSecuredMimeHandler(reg ? true : false, is_system_) && reg)
grt (UTC plus 2) 2011/09/02 19:01:35 "reg ? true : false" -> "reg"
robertshield 2011/09/03 05:36:21 Done.
+ return E_FAIL;
+ }
+ return S_OK;
}
+};
grt (UTC plus 2) 2011/09/02 19:01:35 This seems to have been lost: class CRHActiveDoc :
robertshield 2011/09/03 05:36:21 good catch
- if ((hr == S_OK) && (flags & ACTIVEX)) {
- // We have to call the static T::UpdateRegistry function instead of
- // _AtlModule.UpdateRegistryFromResourceS(IDR_CHROMEFRAME_ACTIVEX, reg)
- // because there is specific OLEMISC replacement.
- hr = ChromeFrameActivex::UpdateRegistry(reg);
+class CRHActiveX : public CustomRegistrationHelper {
+ public:
+ CRHActiveX(UINT reg_flags, bool is_system)
+ : CustomRegistrationHelper(reg_flags, is_system) {}
+
+ private:
+ HRESULT Do(bool reg) {
+ if (reg_flags_ & ACTIVEX) {
+ // We have to call the static T::UpdateRegistry function instead of
+ // _AtlModule.UpdateRegistryFromResourceS(IDR_CHROMEFRAME_ACTIVEX, reg)
+ // because there is specific OLEMISC replacement.
+ return ChromeFrameActivex::UpdateRegistry(reg);
+ }
+ return S_OK;
}
+};
- // Register the elevation policy. We do this only for developer convenience
- // as the installer is really responsible for doing this.
- // Because of that, we do not unregister this policy and just leave that up
- // to the installer.
- if (hr == S_OK && (flags & (ACTIVEDOC | ACTIVEX)) && reg) {
- _AtlModule.UpdateRegistryFromResourceS(IDR_CHROMEFRAME_ELEVATION, reg);
- RefreshElevationPolicy();
+class CRHElevationPolicy : public CustomRegistrationHelper {
+ public:
+ CRHElevationPolicy(UINT reg_flags, bool is_system)
+ : CustomRegistrationHelper(reg_flags, is_system) {}
+
+ private:
+ HRESULT Do(bool reg) {
+ if ((reg_flags_ & (ACTIVEDOC | ACTIVEX)) && reg) {
+ // Register the elevation policy. We do this only for developer
+ // convenience as the installer is really responsible for doing this.
+ // Because of that, we do not unregister this policy and just leave that
+ // up to the installer.
+ _AtlModule.UpdateRegistryFromResourceS(IDR_CHROMEFRAME_ELEVATION, reg);
grt (UTC plus 2) 2011/09/02 19:01:35 why no return this HRESULT?
robertshield 2011/09/03 05:36:21 This is strictly a developer convenience thing. We
+ RefreshElevationPolicy();
grt (UTC plus 2) 2011/09/02 19:01:35 why this not its own step with its own return HRES
robertshield 2011/09/03 05:36:21 Done.
+ }
+ return S_OK;
}
+};
- if ((hr == S_OK) && (flags & GCF_PROTOCOL)) {
- hr = _AtlModule.UpdateRegistryFromResourceS(IDR_CHROMEPROTOCOL, reg);
+class CRHProtocol : public CustomRegistrationHelper {
+ public:
+ CRHProtocol(UINT reg_flags, bool is_system)
+ : CustomRegistrationHelper(reg_flags, is_system) {}
+
+ private:
+ HRESULT Do(bool reg) {
+ if (reg_flags_ & GCF_PROTOCOL) {
+ return _AtlModule.UpdateRegistryFromResourceS(IDR_CHROMEPROTOCOL, reg);
+ }
+ return S_OK;
}
+};
- if ((hr == S_OK) && (flags & BHO_CLSID)) {
- hr = Bho::UpdateRegistry(reg);
+class CRHBhoClsid : public CustomRegistrationHelper {
+ public:
+ CRHBhoClsid(UINT reg_flags, bool is_system)
+ : CustomRegistrationHelper(reg_flags, is_system) {}
+
+ private:
+ HRESULT Do(bool reg) {
+ if (reg_flags_ & BHO_CLSID) {
+ return Bho::UpdateRegistry(reg);
+ }
+ return S_OK;
}
+};
- if ((hr == S_OK) && (flags & BHO_REGISTRATION)) {
- if (is_system) {
- _AtlModule.UpdateRegistryFromResourceS(IDR_REGISTER_BHO, reg);
- } else {
- if (reg) {
- // Setup the long running process:
- SetupUserLevelHelper();
+class CRHBhoIERegistration : public CustomRegistrationHelper {
+ public:
+ CRHBhoIERegistration(UINT reg_flags, bool is_system)
+ : CustomRegistrationHelper(reg_flags, is_system) {}
+
+ private:
+ HRESULT Do(bool reg) {
+ if (reg_flags_ & BHO_REGISTRATION) {
+ if (is_system_) {
+ _AtlModule.UpdateRegistryFromResourceS(IDR_REGISTER_BHO, reg);
grt (UTC plus 2) 2011/09/02 19:01:35 why u no propagate error code?!?!!?
robertshield 2011/09/03 05:36:21 Fixed up the bho registration to proagate error co
} else {
- // Unschedule the user-level helper. Note that we don't kill it here so
- // that during updates we don't have a time window with no running
- // helper. Uninstalls and updates will explicitly kill the helper from
- // within the installer. Unregister existing run-at-startup entry.
- base::win::RemoveCommandFromAutoRun(HKEY_CURRENT_USER, kRunKeyName);
+ if (reg) {
+ // Setup the long running process:
+ SetupUserLevelHelper();
grt (UTC plus 2) 2011/09/02 19:01:35 or here
robertshield 2011/09/03 05:36:21 Done.
+ } else {
+ // Unschedule the user-level helper. Note that we don't kill it here
+ // so that during updates we don't have a time window with no running
+ // helper. Uninstalls and updates will explicitly kill the helper from
+ // within the installer. Unregister existing run-at-startup entry.
+ base::win::RemoveCommandFromAutoRun(HKEY_CURRENT_USER, kRunKeyName);
grt (UTC plus 2) 2011/09/02 19:01:35 eh?
robertshield 2011/09/03 05:36:21 Done.
+ }
}
}
+ return S_OK;
}
+};
- if ((hr == S_OK) && (flags & TYPELIB)) {
- if (reg && !is_system) {
- // Enables the RegisterTypeLib Function function to override default
- // registry mappings under Windows Vista Service Pack 1 (SP1),
- // Windows Server 2008, and later operating system versions
- typedef void (WINAPI* OaEnablePerUserTypeLibReg)(void);
- OaEnablePerUserTypeLibReg per_user_typelib_func =
- reinterpret_cast<OaEnablePerUserTypeLibReg>(
- GetProcAddress(GetModuleHandle(L"oleaut32.dll"),
- "OaEnablePerUserTLibRegistration"));
- if (per_user_typelib_func) {
- (*per_user_typelib_func)();
+class CRHTypeLib : public CustomRegistrationHelper {
+ public:
+ CRHTypeLib(UINT reg_flags, bool is_system)
+ : CustomRegistrationHelper(reg_flags, is_system) {}
+
+ private:
+ HRESULT Do(bool reg) {
+ if (reg_flags_ & TYPELIB) {
+ if (reg && !is_system_) {
+ // Enables the RegisterTypeLib Function function to override default
+ // registry mappings under Windows Vista Service Pack 1 (SP1),
+ // Windows Server 2008, and later operating system versions
+ typedef void (WINAPI* OaEnablePerUserTypeLibReg)(void);
+ OaEnablePerUserTypeLibReg per_user_typelib_func =
+ reinterpret_cast<OaEnablePerUserTypeLibReg>(
+ GetProcAddress(GetModuleHandle(L"oleaut32.dll"),
+ "OaEnablePerUserTLibRegistration"));
+ if (per_user_typelib_func) {
+ (*per_user_typelib_func)();
+ }
}
+ return reg ?
+ UtilRegisterTypeLib(_AtlComModule.m_hInstTypeLib,
+ NULL, !is_system_) :
+ UtilUnRegisterTypeLib(_AtlComModule.m_hInstTypeLib,
+ NULL, !is_system_);
}
- hr = (reg)?
- UtilRegisterTypeLib(_AtlComModule.m_hInstTypeLib, NULL, !is_system) :
- UtilUnRegisterTypeLib(_AtlComModule.m_hInstTypeLib, NULL, !is_system);
+ return S_OK;
}
+};
- // Unconditionally remove NPAPI registration when unregistering any component.
- if ((hr == S_OK) && !reg) {
+class CRHLegacyNPAPICleanup : public CustomRegistrationHelper {
+ public:
+ CRHLegacyNPAPICleanup(UINT reg_flags, bool is_system)
+ : CustomRegistrationHelper(reg_flags, is_system) {}
+
+ private:
+ HRESULT Do(bool reg) {
+ if (!reg) {
+ _AtlModule.UpdateRegistryFromResourceS(IDR_CHROMEFRAME_NPAPI, reg);
grt (UTC plus 2) 2011/09/02 19:01:35 stylistically, i think this should return the erro
robertshield 2011/09/03 05:36:21 I tend to agree, but that means that I would need
grt (UTC plus 2) 2011/09/06 14:56:55 What makes this unregistration code special in tha
+ UtilRemovePersistentNPAPIMarker();
+ }
// Ignore failures.
grt (UTC plus 2) 2011/09/02 19:01:35 bad comment
robertshield 2011/09/03 05:36:21 the comment was correct, just unwanted ;)
grt (UTC plus 2) 2011/09/06 14:56:55 "Bad" in that it is in the wrong location. Methin
- _AtlModule.UpdateRegistryFromResourceS(IDR_CHROMEFRAME_NPAPI, reg);
- UtilRemovePersistentNPAPIMarker();
+ return S_OK;
}
+};
- if (hr == S_OK) {
- hr = _AtlModule.UpdateRegistryAppId(reg);
+class CRHAppId : public CustomRegistrationHelper {
+ public:
+ CRHAppId(UINT reg_flags, bool is_system)
+ : CustomRegistrationHelper(reg_flags, is_system) {}
+
+ private:
+ HRESULT Do(bool reg) {
+ return _AtlModule.UpdateRegistryAppId(reg);
}
+};
- if (hr == S_OK) {
+class CRHUserAgent : public CustomRegistrationHelper {
+ public:
+ CRHUserAgent(UINT reg_flags, bool is_system)
+ : CustomRegistrationHelper(reg_flags, is_system) {}
+
+ private:
+ HRESULT Do(bool reg) {
if (reg) {
- hr = SetChromeFrameUA(is_system, L"1");
+ return SetChromeFrameUA(is_system_, L"1");
} else {
- hr = SetChromeFrameUA(is_system, NULL);
+ return SetChromeFrameUA(is_system_, NULL);
}
}
- return hr;
+};
+
+// Mux the failure step into the hresult. We take only the first four bits
+// and stick those into the top four bits of the facility code. We also set the
+// Customer bit to be polite. Graphically, we write our error code to the
+// bits marked with ^:
+// | 1 2 3 |
+// |0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1|
grt (UTC plus 2) 2011/09/02 19:01:35 Interesting bit number choice. I think it'd be mo
robertshield 2011/09/03 05:36:21 I had copied this from the msdn link below, but su
grt (UTC plus 2) 2011/09/06 14:56:55 Funny: winerror.h has it the other way. :-)
+// |S|R|C|N|X|Facility |Code |
+// ^ ^ ^ ^ ^
+// See http://msdn.microsoft.com/en-us/library/cc231198(PROT.10).aspx for
+// more details on HRESULTS.
+//
+// The resulting error can be extracted by:
+// error_code = (fiddled_hr & 0x07800000) >> 23
+HRESULT MuxErrorIntoHRESULT(HRESULT hr, uint16 error_code) {
+ DCHECK((error_code & 15) == error_code);
grt (UTC plus 2) 2011/09/02 19:01:35 nit: i find 0x0F more obvious than 15. I think er
robertshield 2011/09/03 05:36:21 Done.
+
+ // Check that our four desired bits are clear.
+ // 0xF87FFFFF == 11111000011111111111111111111111
+ DCHECK(static_cast<HRESULT>(hr & 0xF87FFFFF) == hr) << hr;
grt (UTC plus 2) 2011/09/02 19:01:35 DCHECK_EQ(static_cast<HRESULT>(hr & 0xF87FFFFF), h
robertshield 2011/09/03 05:36:21 Done.
+
+ HRESULT fiddled_hr = ((error_code & 15) << 23) | hr;
grt (UTC plus 2) 2011/09/02 19:01:35 15 -> 0x0F and you may need to stick a cast in the
robertshield 2011/09/03 05:36:21 Done.
+ fiddled_hr |= 1 << 29; // Set the customer bit.
+
+ return fiddled_hr;
}
+STDAPI CustomRegistration(UINT reg_flags, BOOL reg, bool is_system) {
grt (UTC plus 2) 2011/09/02 19:01:35 Why is this STDAPI? Change to just returning an H
robertshield 2011/09/03 05:36:21 I think once upon a time this was intended to be a
+ UINT flags = reg_flags;
+ if (reg && (flags & (ACTIVEDOC | ACTIVEX)))
+ flags |= (TYPELIB | GCF_PROTOCOL);
+ HRESULT hr = S_OK;
+
+ // Set the flag that gets checked in AddCommonRGSReplacements before doing
+ // registration work.
+ _AtlModule.do_system_registration_ = is_system;
+
+ ScopedVector<CustomRegistrationHelper> registration_helpers;
grt (UTC plus 2) 2011/09/02 19:01:35 If you stick with the classes and vector approach,
robertshield 2011/09/03 05:36:21 Approach changed.
+ registration_helpers.push_back(
+ new CRHSecuredMimeHandler(reg_flags, is_system)); // 0
grt (UTC plus 2) 2011/09/02 19:01:35 |flags| rather than |reg_flags| should be used her
robertshield 2011/09/03 05:36:21 Done.
+ registration_helpers.push_back(
+ new CRHActiveX(reg_flags, is_system)); // 1
+ registration_helpers.push_back(
+ new CRHElevationPolicy(reg_flags, is_system)); // 2
+ registration_helpers.push_back(
+ new CRHProtocol(reg_flags, is_system)); // 3
+ registration_helpers.push_back(
+ new CRHBhoClsid(reg_flags, is_system)); // 4
+ registration_helpers.push_back(
+ new CRHBhoIERegistration(reg_flags, is_system)); // 5
+ registration_helpers.push_back(
+ new CRHTypeLib(reg_flags, is_system)); // 6
+ registration_helpers.push_back(
+ new CRHLegacyNPAPICleanup(reg_flags, is_system)); // 7
+ registration_helpers.push_back(
+ new CRHAppId(reg_flags, is_system)); // 8
+ registration_helpers.push_back(
+ new CRHUserAgent(reg_flags, is_system)); // 9
+
+ ScopedVector<CustomRegistrationHelper>::iterator reg_iter(
+ registration_helpers->begin());
+
+ bool do_register = (reg == TRUE);
grt (UTC plus 2) 2011/09/02 19:01:35 reg != FALSE, unless you take my request to change
robertshield 2011/09/03 05:36:21 Done.
+ bool rollback = false;
+
+ // This value will be muxed into the hresult in case of failure. It will
+ // correspond to the index of the failing step.
grt (UTC plus 2) 2011/09/02 19:01:35 Using the index of the step introduces a requireme
robertshield 2011/09/03 05:36:21 Thought about that but figured it would add even m
grt (UTC plus 2) 2011/09/06 14:56:55 It just means that you have to refer to the exact
+ uint16 registration_failure_step = 0;
grt (UTC plus 2) 2011/09/02 19:01:35 The arbiters of style say to use "int" for this.
robertshield 2011/09/03 05:36:21 Done.
+
+ for (; reg_iter != registration_helpers->end(); ++reg_iter) {
+ if (!SUCCEEDED(hr = (*reg_iter)->Run(do_register))) {
grt (UTC plus 2) 2011/09/02 19:01:35 I don't know that this is banned by the style guid
robertshield 2011/09/03 05:36:21 Done.
+ if (do_register) {
+ // Only rollback during registration. During unregistration keep going.
+ rollback = true;
+ break;
+ }
+ }
+ registration_failure_step++;
+ }
+
+ if (rollback) {
+ // Rollback all actions that preceded reg_iter's current position. Note that
+ // this does not rollback the failing action.
grt (UTC plus 2) 2011/09/02 19:01:35 Consider rolling back the failing action. Otherwi
robertshield 2011/09/03 05:36:21 Done.
+ ScopedVector<CustomRegistrationHelper>::reverse_iterator rollback_iter(
grt (UTC plus 2) 2011/09/02 19:01:35 I don't see an advantage to making a new object fo
robertshield 2011/09/03 05:36:21 Changed to use an index.
+ reg_iter);
+ for (; rollback_iter != registration_helpers->rend(); ++rollback_iter) {
+ (*rollback_iter)->Rollback(do_register);
+ }
+ }
+
+ return MuxErrorIntoHRESULT(hr, registration_failure_step);
grt (UTC plus 2) 2011/09/02 19:01:35 Consider changing SelfRegWorkItem::RegisterDll as
robertshield 2011/09/03 05:36:21 Good idea, so changed.
+}
+
// DllRegisterServer - Adds entries to the system registry
STDAPI DllRegisterServer() {
UINT flags = ACTIVEX | ACTIVEDOC | TYPELIB | GCF_PROTOCOL |
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698