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
3 // found in the LICENSE file.
5 #ifndef CHROME_FRAME_URLMON_MONIKER_H_
6 #define CHROME_FRAME_URLMON_MONIKER_H_
13 #include "base/lazy_instance.h"
14 #include "base/logging.h"
15 #include "base/threading/thread_local.h"
16 #include "base/win/scoped_variant.h"
17 #include "googleurl/src/gurl.h"
18 #include "chrome_frame/utils.h"
20 // This file contains classes that are used to cache the contents of a top-level
21 // http request (not for sub frames) while that request is parsed for the
22 // presence of a meta tag indicating that the page should be rendered in CF.
24 // Here are a few scenarios we handle and how the classes come to play.
27 // Scenario 1: Non CF url navigation through address bar (www.msn.com)
28 // - Bho::BeforeNavigate - top level url = www.msn.com
29 // - MSHTML -> MonikerPatch::BindToStorage.
30 // (IEFrame starts this by calling mshtml!*SuperNavigate*)
31 // - check if the url is a top level url
32 // - iff the url is a top level url, we switch in our own callback object
33 // and hook it up to the bind context (BSCBStorageBind)
34 // - otherwise just call the original
35 // - BSCBStorageBind::OnDataAvailable - sniffs data and determines that the
36 // renderer is not chrome. Goes into pass through mode.
37 // - The page loads in mshtml.
41 // Scenario 2: CF navigation through address bar URL
42 // - Bho::BeforeNavigate - top level url = http://wave.google.com/
43 // - MSHTML -> MonikerPatch::BindToStorage.
44 // (IEFrame starts this by calling mshtml!*SuperNavigate*)
45 // - request_data is NULL
46 // - check if the url is a top level url
47 // - iff the url is a top level url, we switch in our own callback object
48 // and hook it up to the bind context (BSCBStorageBind)
49 // - BSCBStorageBind::OnDataAvailable - sniffs data and determines that the
50 // renderer is chrome. It then registers a special bind context param and
51 // sets a magic clip format in the format_etc. Then goes into pass through
53 // - mshtml looks at the clip format and re-issues the navigation with the
54 // same bind context. Also returns INET_E_TERMINATED_BIND so that same
55 // underlying transaction objects are used.
56 // - IEFrame -> MonikerPatch::BindToStorage
57 // - We check for the special bind context param and instantiate and
58 // return our ActiveDoc
61 // Scenario 3: CF navigation through mshtml link
62 // Same as scenario #2.
66 // Scenario 4: CF navigation through link click in chrome loads non CF page
67 // - Link click comes to ChromeActiveDocument::OnOpenURL
68 // - web_browser->Navigate with URL
73 // Scenario 5: CF navigation through link click in chrome loads CF page
74 // - Link click comes to ChromeActiveDocument::OnOpenURL
75 // - web_browser->Navigate with URL
79 // This class is the link between a few static, moniker related functions to
80 // the bho. The specific services needed by those functions are abstracted into
81 // this interface for easier testability.
82 class NavigationManager
{
87 // Returns the Bho instance for the current thread. This is returned from
88 // TLS. Returns NULL if no instance exists on the current thread.
89 static NavigationManager
* GetThreadInstance();
91 void RegisterThreadInstance();
92 void UnregisterThreadInstance();
94 virtual ~NavigationManager() {
95 DCHECK(GetThreadInstance() != this);
98 // Returns the url of the current top level navigation.
99 const std::wstring
& url() const {
103 // Called to set the current top level URL that's being navigated to.
104 void set_url(const wchar_t* url
) {
105 DVLOG(1) << __FUNCTION__
<< " " << url
;
109 // Returns the referrer header value of the current top level navigation.
110 const std::string
& referrer() const {
114 void set_referrer(const std::string
& referrer
) {
115 referrer_
= referrer
;
118 // Return true if this is a URL that represents a top-level
119 // document that might have to be rendered in CF.
120 virtual bool IsTopLevelUrl(const wchar_t* url
);
122 // Called when we've detected the http-equiv meta tag in the current page
123 // and need to switch over from mshtml to CF.
124 virtual HRESULT
NavigateToCurrentUrlInCF(IBrowserService
* browser
);
126 void set_post_data(VARIANT
* post_data
) {
129 if (V_VT(post_data
) == (VT_BYREF
| VT_VARIANT
)) {
130 post_data_
.Set(*post_data
->pvarVal
);
132 NOTREACHED() << "unexpected type for post_data: "
133 << std::hex
<< post_data
->vt
;
138 const base::win::ScopedVariant
& post_data() const {
142 void set_headers(VARIANT
* headers
) {
149 const base::win::ScopedVariant
& headers() const {
154 std::string referrer_
;
156 base::win::ScopedVariant post_data_
;
157 base::win::ScopedVariant headers_
;
159 static base::LazyInstance
<base::ThreadLocalPointer
<NavigationManager
> >
163 DISALLOW_COPY_AND_ASSIGN(NavigationManager
);
166 // static-only class that manages an IMoniker patch.
167 // We need this patch to stay in the loop when top-level HTML content is
168 // downloaded that might have the CF http-equiv meta tag.
169 // When we detect candidates for those requests, we add our own callback
170 // object (as explained at the top of this file) and use it to cache the
171 // original document contents in order to avoid multiple network trips
172 // if we need to switch the renderer over to CF.
174 MonikerPatch() {} // no instances should be created of this class.
176 // Patches two IMoniker methods, BindToObject and BindToStorage.
177 static bool Initialize();
179 // Nullifies the IMoniker patches.
180 static void Uninitialize();
182 // Typedefs for IMoniker methods.
183 typedef HRESULT (STDMETHODCALLTYPE
* IMoniker_BindToObject_Fn
)(IMoniker
* me
,
184 IBindCtx
* bind_ctx
, IMoniker
* to_left
, REFIID iid
, void** obj
);
185 typedef HRESULT (STDMETHODCALLTYPE
* IMoniker_BindToStorage_Fn
)(IMoniker
* me
,
186 IBindCtx
* bind_ctx
, IMoniker
* to_left
, REFIID iid
, void** obj
);
188 static STDMETHODIMP
BindToObject(IMoniker_BindToObject_Fn original
,
189 IMoniker
* me
, IBindCtx
* bind_ctx
,
190 IMoniker
* to_left
, REFIID iid
, void** obj
);
192 static STDMETHODIMP
BindToStorage(IMoniker_BindToStorage_Fn original
,
193 IMoniker
* me
, IBindCtx
* bind_ctx
,
194 IMoniker
* to_left
, REFIID iid
, void** obj
);
198 extern wchar_t* kChromeRequestParam
;
200 #endif // CHROME_FRAME_URLMON_MONIKER_H_