Chromium Code Reviews| 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 | |