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
3 // found in the LICENSE file.
5 #ifndef CHROME_FRAME_UTILS_H_
6 #define CHROME_FRAME_UTILS_H_
15 #include "base/basictypes.h"
16 #include "base/logging.h"
17 #include "base/metrics/histogram.h"
18 #include "base/strings/string16.h"
19 #include "base/win/scoped_comptr.h"
20 #include "ui/gfx/rect.h"
23 class RegistryListPreferencesHolder
;
24 interface IBrowserService
;
25 interface IWebBrowser2
;
26 struct ContextMenuModel
;
32 // utils.h : Various utility functions and classes
33 extern const char kGCFProtocol
[];
35 extern const wchar_t kAllowUnsafeURLs
[];
36 extern const wchar_t kChromeContentPrefix
[];
37 extern const wchar_t kChromeFrameAccessibleMode
[];
38 extern const wchar_t kChromeFrameAttachTabPattern
[];
39 extern const wchar_t kChromeFrameConfigKey
[];
40 extern const wchar_t kChromeFrameHeadlessMode
[];
41 extern const wchar_t kChromeFrameUnpinnedMode
[];
42 extern const wchar_t kChromeMimeType
[];
43 extern const wchar_t kChromeProtocolPrefix
[];
44 extern const wchar_t kEnableBuggyBhoIntercept
[];
45 extern const wchar_t kEnableGCFRendererByDefault
[];
46 extern const wchar_t kExcludeUAFromDomainList
[];
47 extern const wchar_t kIexploreProfileName
[];
48 extern const wchar_t kRenderInGCFUrlList
[];
49 extern const wchar_t kRenderInHostUrlList
[];
50 extern const wchar_t kRundllProfileName
[];
51 extern const wchar_t kUseBackgroundThreadForSubResources
[];
53 // This function is very similar to the AtlRegisterTypeLib function except
54 // that it takes a parameter that specifies whether to register the typelib
55 // for the current user only or on a machine-wide basis
56 // Refer to the MSDN documentation for AtlRegisterTypeLib for a description of
58 HRESULT
UtilRegisterTypeLib(HINSTANCE tlb_instance
,
60 bool for_current_user_only
);
62 // This function is very similar to the AtlUnRegisterTypeLib function except
63 // that it takes a parameter that specifies whether to unregister the typelib
64 // for the current user only or on a machine-wide basis
65 // Refer to the MSDN documentation for AtlUnRegisterTypeLib for a description
67 HRESULT
UtilUnRegisterTypeLib(HINSTANCE tlb_instance
,
69 bool for_current_user_only
);
71 HRESULT
UtilRegisterTypeLib(LPCWSTR typelib_path
, bool for_current_user_only
);
73 HRESULT
UtilUnRegisterTypeLib(LPCWSTR typelib_path
, bool for_current_user_only
);
75 HRESULT
UtilRegisterTypeLib(ITypeLib
* typelib
,
78 bool for_current_user_only
);
80 HRESULT
UtilUnRegisterTypeLib(ITypeLib
* typelib
,
81 bool for_current_user_only
);
83 // Clears a marker that causes legacy NPAPI registration to persist across
84 // updates. Returns false if the marker could not be removed.
85 bool UtilRemovePersistentNPAPIMarker();
87 // Given an HTML fragment, this function looks for the
88 // <meta http-equiv="X-UA-Compatible"> tag and extracts the value of the
89 // "content" attribute
90 // This method will currently return a false positive if the tag appears
91 // inside a string in a <SCRIPT> block.
92 HRESULT
UtilGetXUACompatContentValue(const std::wstring
& html_string
,
93 std::wstring
* content_value
);
95 // Returns a string from ChromeFrame's string table by resource. Must be
96 // provided with a valid resource id.
97 std::wstring
GetResourceString(int resource_id
);
99 // Displays a message box indicating that there was a version mismatch between
100 // ChromeFrame and the running instance of Chrome.
101 // server_version is the version of the running instance of Chrome.
102 void DisplayVersionMismatchWarning(HWND parent
,
103 const std::string
& server_version
);
105 // This class provides a base implementation for ATL modules which want to
106 // perform all their registration under HKCU. This class overrides the
107 // RegisterServer and UnregisterServer methods and registers the type libraries
108 // under HKCU (the rest of the registration is made under HKCU by changing the
109 // appropriate .RGS files)
110 template < class BaseAtlModule
>
111 class AtlPerUserModule
: public BaseAtlModule
{
113 HRESULT
RegisterServer(BOOL reg_typelib
= FALSE
,
114 const CLSID
* clsid
= NULL
) throw() {
115 HRESULT hr
= BaseAtlModule::RegisterServer(FALSE
, clsid
);
120 hr
= UtilRegisterTypeLib(_AtlComModule
.m_hInstTypeLib
, NULL
, false);
125 HRESULT
UnregisterServer(BOOL unreg_typelib
,
126 const CLSID
* clsid
= NULL
) throw() {
127 HRESULT hr
= BaseAtlModule::UnregisterServer(FALSE
, clsid
);
132 hr
= UtilUnRegisterTypeLib(_AtlComModule
.m_hInstTypeLib
, NULL
, false);
138 // Creates a javascript statement for execution from the function name and
139 // arguments passed in.
140 std::string
CreateJavascript(const std::string
& function_name
,
141 const std::string args
);
143 // Use to prevent the DLL from being unloaded while there are still living
144 // objects with outstanding references.
151 // Retrieves the executable name of the process hosting us. If
152 // |include_extension| is false, then we strip the extension from the name.
153 std::wstring
GetHostProcessName(bool include_extension
);
155 typedef enum BrowserType
{
156 BROWSER_INVALID
= -1,
161 BrowserType
GetBrowserType();
163 typedef enum IEVersion
{
175 // The renderer to be used for a page. Values for Chrome also convey the
176 // reason why Chrome is used.
178 RENDERER_TYPE_UNDETERMINED
= 0,
179 RENDERER_TYPE_CHROME_MIN
,
180 // NOTE: group all _CHROME_ values together below here, as they are used for
181 // generating metrics reported via UMA (adjust MIN/MAX as needed).
182 RENDERER_TYPE_CHROME_GCF_PROTOCOL
= RENDERER_TYPE_CHROME_MIN
,
183 RENDERER_TYPE_CHROME_HTTP_EQUIV
,
184 RENDERER_TYPE_CHROME_RESPONSE_HEADER
,
185 RENDERER_TYPE_CHROME_DEFAULT_RENDERER
,
186 RENDERER_TYPE_CHROME_OPT_IN_URL
,
187 RENDERER_TYPE_CHROME_WIDGET
,
188 // NOTE: all _CHOME_ values must go above here (adjust MIN/MAX as needed).
189 RENDERER_TYPE_CHROME_MAX
= RENDERER_TYPE_CHROME_WIDGET
,
193 // Returns true if the given RendererType represents Chrome.
194 bool IsChrome(RendererType renderer_type
);
196 // Convenience macro for logging a sample for the launch type metric.
197 #define UMA_LAUNCH_TYPE_COUNT(sample) \
198 UMA_HISTOGRAM_CUSTOM_COUNTS("ChromeFrame.LaunchType", sample, \
199 RENDERER_TYPE_CHROME_MIN, RENDERER_TYPE_CHROME_MAX, \
200 RENDERER_TYPE_CHROME_MAX + 1 - RENDERER_TYPE_CHROME_MIN)
202 // To get the IE version when Chrome Frame is hosted in IE. Make sure that
203 // the hosting browser is IE before calling this function, otherwise NON_IE
206 // Versions newer than the newest supported version are reported as the newest
207 // supported version.
208 IEVersion
GetIEVersion();
210 // Returns the actual major version of the IE in which the current process is
211 // hosted. Returns 0 if the current process is not IE or any other error occurs.
212 uint32
GetIEMajorVersion();
214 base::FilePath
GetIETemporaryFilesFolder();
216 // Retrieves the file version from a module handle without extra round trips
217 // to the disk (as happens with the regular GetFileVersionInfo API).
219 // @param module A handle to the module for which to retrieve the version info.
220 // @param high On successful return holds the most significant part of the file
221 // version. Must be non-null.
222 // @param low On successful return holds the least significant part of the file
223 // version. May be NULL.
224 // @returns true if the version info was successfully retrieved.
225 bool GetModuleVersion(HMODULE module
, uint32
* high
, uint32
* low
);
227 // Return if the IEXPLORE is in private mode. The IEIsInPrivateBrowsing() checks
228 // whether current process is IEXPLORE.
229 bool IsIEInPrivate();
231 // Calls [ieframe|shdocvw]!DoFileDownload to initiate a download.
232 HRESULT
DoFileDownloadInIE(const wchar_t* url
);
234 // Construct a menu from the model sent from Chrome.
235 HMENU
BuildContextMenu(const ContextMenuModel
& menu_model
);
237 // Uses GURL internally to append 'relative' to 'document'
238 std::string
ResolveURL(const std::string
& document
,
239 const std::string
& relative
);
241 // Returns true iff the two urls have the same scheme, same host and same port.
242 bool HaveSameOrigin(const std::string
& url1
, const std::string
& url2
);
244 // Get a boolean configuration value from registry.
245 bool GetConfigBool(bool default_value
, const wchar_t* value_name
);
247 // Gets an integer configuration value from the registry.
248 int GetConfigInt(int default_value
, const wchar_t* value_name
);
250 // Gets a 64-bit integer configuration value from the registry.
251 int64
GetConfigInt64(int64 default_value
, const wchar_t* value_name
);
253 // Sets an integer configuration value in the registry.
254 bool SetConfigInt(const wchar_t* value_name
, int value
);
256 // Sets a boolean integer configuration value in the registry.
257 bool SetConfigBool(const wchar_t* value_name
, bool value
);
259 // Sets a 64-bit integer configuration value in the registry.
260 bool SetConfigInt64(const wchar_t* value_name
, int64 value
);
262 // Deletes the configuration value passed in.
263 bool DeleteConfigValue(const wchar_t* value_name
);
265 // Returns true if we are running in headless mode in which case we need to
266 // gather crash dumps, etc to send them to the crash server.
267 bool IsHeadlessMode();
269 // Returns true if we are running in accessible mode in which we need to enable
270 // renderer accessibility for use in automation.
271 bool IsAccessibleMode();
273 // Returns true if we are running in unpinned mode in which case DLL
274 // eviction should be possible.
275 bool IsUnpinnedMode();
277 // Returns true if all HTML pages should be rendered in GCF by default.
278 bool IsGcfDefaultRenderer();
280 // Returns true if the presence of
281 // <meta http-equiv="X-UA-Compatible" content="chrome=1">
282 // in HTML pages should be ignored
283 bool SkipMetadataCheck();
285 // Check if this url is opting into Chrome Frame based on static settings.
287 // - RENDERER_TYPE_UNDETERMINED if not opt-in or if explicit opt-out
288 // - RENDERER_TYPE_CHROME_DEFAULT_RENDERER
289 // - RENDERER_TYPE_CHROME_OPT_IN_URL
290 RendererType
RendererTypeForUrl(const std::wstring
& url
);
292 // Check if we should try to remove the CF user agent based on registry
294 bool ShouldRemoveUAForUrl(const string16
& url
);
296 // Testing methods that return the backing stores behind RendererTypeForUrl and
297 // ShouldRemoveUAForUrl. Intended to allow unit testing code that calls the
299 // TODO(robertshield): All of the FooForUrl code should be removed from here
300 // and further refactored.
301 RegistryListPreferencesHolder
& GetRendererTypePreferencesHolderForTesting();
302 RegistryListPreferencesHolder
& GetUserAgentPreferencesHolderForTesting();
304 // A shortcut for QueryService
305 template <typename T
>
306 HRESULT
DoQueryService(const IID
& service_id
, IUnknown
* unk
, T
** service
) {
311 base::win::ScopedComPtr
<IServiceProvider
> service_provider
;
312 HRESULT hr
= service_provider
.QueryFrom(unk
);
313 if (service_provider
)
314 hr
= service_provider
->QueryService(service_id
, service
);
316 DCHECK(FAILED(hr
) || *service
);
320 // Navigates an IWebBrowser2 object to a moniker.
321 // |headers| can be NULL.
322 HRESULT
NavigateBrowserToMoniker(IUnknown
* browser
, IMoniker
* moniker
,
323 const wchar_t* headers
, IBindCtx
* bind_ctx
,
324 const wchar_t* fragment
, IStream
* post_data
,
327 // Raises a flag on the current thread (using TLS) to indicate that an
328 // in-progress navigation should be rendered in chrome frame.
329 void MarkBrowserOnThreadForCFNavigation(IBrowserService
* browser
);
331 // Checks if this browser instance has been marked as currently navigating
332 // to a CF document. If clear_flag is set to true, the tls flag is cleared but
333 // only if the browser has been marked.
334 bool CheckForCFNavigation(IBrowserService
* browser
, bool clear_flag
);
336 // Returns true if the URL passed in is something which can be handled by
337 // Chrome. If this function returns false then we should fail the navigation.
338 // When is_privileged is true, chrome extension URLs will be considered valid.
339 bool IsValidUrlScheme(const GURL
& url
, bool is_privileged
);
341 // Returns the raw http headers for the current request given an
342 // IWinInetHttpInfo pointer.
343 std::string
GetRawHttpHeaders(IWinInetHttpInfo
* info
);
345 // Can be used to determine whether a given request is being performed for
346 // a sub-frame or iframe in Internet Explorer. This can be called
347 // from various places, notably in request callbacks and the like.
349 // |service_provider| must not be NULL and should be a pointer to something
350 // that implements IServiceProvider (if it isn't this method returns false).
352 // Returns true if this method can determine with some certainty that the
353 // request did NOT originate from a top level frame, returns false otherwise.
354 bool IsSubFrameRequest(IUnknown
* service_provider
);
356 // See COM_INTERFACE_BLIND_DELEGATE below for details.
358 STDMETHODIMP
CheckOutgoingInterface(void* obj
, REFIID iid
, void** ret
,
360 T
* instance
= reinterpret_cast<T
*>(obj
);
361 HRESULT hr
= E_NOINTERFACE
;
362 IUnknown
* delegate
= instance
? instance
->delegate() : NULL
;
364 hr
= delegate
->QueryInterface(iid
, ret
);
367 wchar_t iid_string
[64] = {0};
368 StringFromGUID2(iid
, iid_string
, arraysize(iid_string
));
369 DVLOG(1) << __FUNCTION__
<< " Giving out wrapped interface: "
378 // See COM_INTERFACE_ENTRY_IF_DELEGATE_SUPPORTS below for details.
380 STDMETHODIMP
QueryInterfaceIfDelegateSupports(void* obj
, REFIID iid
,
381 void** ret
, DWORD cookie
) {
382 HRESULT hr
= E_NOINTERFACE
;
383 T
* instance
= reinterpret_cast<T
*>(obj
);
384 IUnknown
* delegate
= instance
? instance
->delegate() : NULL
;
386 base::win::ScopedComPtr
<IUnknown
> original
;
387 hr
= delegate
->QueryInterface(iid
,
388 reinterpret_cast<void**>(original
.Receive()));
390 IUnknown
* supported_interface
= reinterpret_cast<IUnknown
*>(
391 reinterpret_cast<DWORD_PTR
>(obj
) + cookie
);
392 supported_interface
->AddRef();
393 *ret
= supported_interface
;
401 // Same as COM_INTERFACE_ENTRY but relies on the class to implement a
402 // delegate() method that returns a pointer to the delegated COM object.
403 #define COM_INTERFACE_ENTRY_IF_DELEGATE_SUPPORTS(x) \
404 COM_INTERFACE_ENTRY_FUNC(_ATL_IIDOF(x), \
405 offsetofclass(x, _ComMapClass), \
406 QueryInterfaceIfDelegateSupports<_ComMapClass>)
408 // Queries the delegated COM object for an interface, bypassing the wrapper.
409 #define COM_INTERFACE_BLIND_DELEGATE() \
410 COM_INTERFACE_ENTRY_FUNC_BLIND(0, CheckOutgoingInterface<_ComMapClass>)
412 std::wstring
GuidToString(const GUID
& guid
);
414 // The urls retrieved from the IMoniker interface don't contain the anchor
415 // portion of the actual url navigated to. This function checks whether the
416 // url passed in the bho_url parameter contains an anchor and if yes checks
417 // whether it matches the url retrieved from the moniker. If yes it returns
418 // the bho url, if not the moniker url.
419 std::wstring
GetActualUrlFromMoniker(IMoniker
* moniker
,
420 IBindCtx
* bind_context
,
421 const std::wstring
& bho_url
);
423 // Checks if a window is a top level window
424 bool IsTopLevelWindow(HWND window
);
426 // Seeks a stream back to position 0.
427 HRESULT
RewindStream(IStream
* stream
);
429 // Fired when we want to notify IE about privacy changes.
430 #define WM_FIRE_PRIVACY_CHANGE_NOTIFICATION (WM_APP + 1)
432 // Sent (not posted) when a request needs to be downloaded in the host browser
433 // instead of Chrome. WPARAM is 0 and LPARAM is a pointer to an IMoniker
435 // NOTE: Since the message is sent synchronously, the handler should only
436 // start asynchronous operations in order to not block the sender unnecessarily.
437 #define WM_DOWNLOAD_IN_HOST (WM_APP + 2)
439 // This structure contains the parameters sent over to initiate a download
440 // request in the host browser.
441 struct DownloadInHostParams
{
442 base::win::ScopedComPtr
<IBindCtx
> bind_ctx
;
443 base::win::ScopedComPtr
<IMoniker
> moniker
;
444 base::win::ScopedComPtr
<IStream
> post_data
;
445 std::string request_headers
;
448 // Maps the InternetCookieState enum to the corresponding CookieAction values
449 // used for IE privacy stuff.
450 int32
MapCookieStateToCookieAction(InternetCookieState cookie_state
);
452 // Parses the url passed in and returns a GURL instance without the fragment.
453 GURL
GetUrlWithoutFragment(const wchar_t* url
);
455 // Compares the URLs passed in after removing the fragments from them.
456 bool CompareUrlsWithoutFragment(const wchar_t* url1
, const wchar_t* url2
);
458 // Returns the Referrer from the HTTP headers and additional headers.
459 std::string
FindReferrerFromHeaders(const wchar_t* headers
,
460 const wchar_t* additional_headers
);
462 // Returns the HTTP headers from the binding passed in.
463 std::string
GetHttpHeadersFromBinding(IBinding
* binding
);
465 // Returns the HTTP response code from the binding passed in.
466 int GetHttpResponseStatusFromBinding(IBinding
* binding
);
468 // Returns the clipboard format for text/html.
469 CLIPFORMAT
GetTextHtmlClipboardFormat();
471 // Returns true iff the mime type is text/html.
472 bool IsTextHtmlMimeType(const wchar_t* mime_type
);
474 // Returns true iff the clipboard format is text/html.
475 bool IsTextHtmlClipFormat(CLIPFORMAT cf
);
477 // Returns true if we can detect that we are running as SYSTEM, false otherwise.
478 bool IsSystemProcess();
480 // STL helper class that implements a functor to delete objects.
481 // E.g: std::for_each(v.begin(), v.end(), utils::DeleteObject());
485 template <typename T
>
486 void operator()(T
* obj
) {
492 // Convert various protocol flags to text representation. Used for logging.
493 std::string
BindStatus2Str(ULONG bind_status
);
494 std::string
PiFlags2Str(DWORD flags
);
495 std::string
Bscf2Str(DWORD flags
);
497 // Reads data from a stream into a string.
498 HRESULT
ReadStream(IStream
* stream
, size_t size
, std::string
* data
);
500 // Parses urls targeted at ChromeFrame. This class maintains state like
501 // whether a url is prefixed with the gcf: prefix, whether it is being
502 // attached to an existing external tab, etc.
503 class ChromeFrameUrl
{
507 // Parses the url passed in. Returns true on success.
508 bool Parse(const std::wstring
& url
);
510 bool is_chrome_protocol() const {
511 return is_chrome_protocol_
;
514 bool attach_to_external_tab() const {
515 return attach_to_external_tab_
;
518 uint64
cookie() const {
522 int disposition() const {
526 const gfx::Rect
& dimensions() const {
530 const GURL
& gurl() const {
534 const std::string
& profile_name() const {
535 return profile_name_
;
539 // If we are attaching to an existing external tab, this function parses the
540 // suffix portion of the URL which contains the attach_external_tab prefix.
541 bool ParseAttachExternalTabUrl();
546 bool attach_to_external_tab_
;
547 bool is_chrome_protocol_
;
549 gfx::Rect dimensions_
;
553 std::string profile_name_
;
556 class NavigationConstraints
;
557 // Returns true if we can navigate to this URL.
558 // These decisions are controlled by the NavigationConstraints object passed
560 bool CanNavigate(const GURL
& url
,
561 NavigationConstraints
* navigation_constraints
);
563 // Helper function to spin a message loop and dispatch messages while waiting
564 // for a handle to be signaled.
565 void WaitWithMessageLoop(HANDLE
* handles
, int count
, DWORD timeout
);
567 // Enumerates values in a key and adds them to an array.
568 // The names of the values are not returned.
569 void EnumerateKeyValues(HKEY parent_key
, const wchar_t* sub_key_name
,
570 std::vector
<std::wstring
>* values
);
572 // Interprets the value of an X-UA-Compatible header (or <meta> tag equivalent)
573 // and indicates whether the header value contains a Chrome Frame directive
574 // matching a given host browser version.
576 // The header is a series of name-value pairs, with the names being HTTP tokens
577 // and the values being either tokens or quoted-strings. Names and values are
578 // joined by '=' and pairs are delimited by either ';' or ','. LWS may be used
579 // liberally before and between names, values, '=', and ';' or ','. See RFC 2616
580 // for definitions of token, quoted-string, and LWS. See Microsoft's
581 // documentation of the X-UA-COMPATIBLE header here:
582 // http://msdn.microsoft.com/en-us/library/cc288325(VS.85).aspx
584 // At most one 'Chrome=<FILTER>' entry is expected in the header value. The
585 // first valid instance is used. The value of "<FILTER>" (possibly after
586 // unquoting) is interpreted as follows:
588 // "1" - Always active
589 // "IE7" - Active for IE major version 7 or lower
592 // X-UA-Compatible: IE=8; Chrome=IE6
594 // The string is first interpreted using ';' as a delimiter. It is reevaluated
595 // using ',' iff no valid 'chrome=' value is found.
596 bool CheckXUaCompatibleDirective(const std::string
& directive
,
597 int ie_major_version
);
599 // Returns the version of the current module as a string.
600 std::wstring
GetCurrentModuleVersion();
602 // Returns true if ChromeFrame is the currently loaded document.
603 bool IsChromeFrameDocument(IWebBrowser2
* web_browser
);
605 // Increases the wininet connection limit for HTTP 1.0/1.1 connections to the
606 // value passed in. This is only done if the existing connection limit is
607 // lesser than the connection limit passed in. This function attempts to
608 // increase the connection count once per process.
609 // Returns true on success.
610 bool IncreaseWinInetConnections(DWORD connections
);
612 // Sets |profile_path| to the path for the Chrome Frame |profile_name|
614 void GetChromeFrameProfilePath(const string16
& profile_name
,
615 base::FilePath
* profile_path
);
617 #endif // CHROME_FRAME_UTILS_H_