OLD | NEW |
| (Empty) |
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. | |
4 | |
5 #ifndef CHROME_FRAME_URLMON_MONIKER_H_ | |
6 #define CHROME_FRAME_URLMON_MONIKER_H_ | |
7 | |
8 #include <atlbase.h> | |
9 #include <atlcom.h> | |
10 #include <urlmon.h> | |
11 #include <string> | |
12 | |
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 "chrome_frame/utils.h" | |
18 | |
19 // This file contains classes that are used to cache the contents of a top-level | |
20 // http request (not for sub frames) while that request is parsed for the | |
21 // presence of a meta tag indicating that the page should be rendered in CF. | |
22 | |
23 // Here are a few scenarios we handle and how the classes come to play. | |
24 | |
25 // | |
26 // Scenario 1: Non CF url navigation through address bar (www.msn.com) | |
27 // - Bho::BeforeNavigate - top level url = www.msn.com | |
28 // - MSHTML -> MonikerPatch::BindToStorage. | |
29 // (IEFrame starts this by calling mshtml!*SuperNavigate*) | |
30 // - check if the url is a top level url | |
31 // - iff the url is a top level url, we switch in our own callback object | |
32 // and hook it up to the bind context (BSCBStorageBind) | |
33 // - otherwise just call the original | |
34 // - BSCBStorageBind::OnDataAvailable - sniffs data and determines that the | |
35 // renderer is not chrome. Goes into pass through mode. | |
36 // - The page loads in mshtml. | |
37 // | |
38 | |
39 // | |
40 // Scenario 2: CF navigation through address bar URL | |
41 // - Bho::BeforeNavigate - top level url = http://wave.google.com/ | |
42 // - MSHTML -> MonikerPatch::BindToStorage. | |
43 // (IEFrame starts this by calling mshtml!*SuperNavigate*) | |
44 // - request_data is NULL | |
45 // - check if the url is a top level url | |
46 // - iff the url is a top level url, we switch in our own callback object | |
47 // and hook it up to the bind context (BSCBStorageBind) | |
48 // - BSCBStorageBind::OnDataAvailable - sniffs data and determines that the | |
49 // renderer is chrome. It then registers a special bind context param and | |
50 // sets a magic clip format in the format_etc. Then goes into pass through | |
51 // mode. | |
52 // - mshtml looks at the clip format and re-issues the navigation with the | |
53 // same bind context. Also returns INET_E_TERMINATED_BIND so that same | |
54 // underlying transaction objects are used. | |
55 // - IEFrame -> MonikerPatch::BindToStorage | |
56 // - We check for the special bind context param and instantiate and | |
57 // return our ActiveDoc | |
58 | |
59 // | |
60 // Scenario 3: CF navigation through mshtml link | |
61 // Same as scenario #2. | |
62 // | |
63 | |
64 // | |
65 // Scenario 4: CF navigation through link click in chrome loads non CF page | |
66 // - Link click comes to ChromeActiveDocument::OnOpenURL | |
67 // - web_browser->Navigate with URL | |
68 // - [Scenario 1] | |
69 // | |
70 | |
71 // | |
72 // Scenario 5: CF navigation through link click in chrome loads CF page | |
73 // - Link click comes to ChromeActiveDocument::OnOpenURL | |
74 // - web_browser->Navigate with URL | |
75 // - [Scenario 2] | |
76 // | |
77 | |
78 // This class is the link between a few static, moniker related functions to | |
79 // the bho. The specific services needed by those functions are abstracted into | |
80 // this interface for easier testability. | |
81 class NavigationManager { | |
82 public: | |
83 NavigationManager() { | |
84 } | |
85 | |
86 // Returns the Bho instance for the current thread. This is returned from | |
87 // TLS. Returns NULL if no instance exists on the current thread. | |
88 static NavigationManager* GetThreadInstance(); | |
89 | |
90 void RegisterThreadInstance(); | |
91 void UnregisterThreadInstance(); | |
92 | |
93 virtual ~NavigationManager() { | |
94 DCHECK(GetThreadInstance() != this); | |
95 } | |
96 | |
97 // Returns the url of the current top level navigation. | |
98 const std::wstring& url() const { | |
99 return url_; | |
100 } | |
101 | |
102 // Called to set the current top level URL that's being navigated to. | |
103 void set_url(const wchar_t* url) { | |
104 DVLOG(1) << __FUNCTION__ << " " << url; | |
105 url_ = url; | |
106 } | |
107 | |
108 // Returns the referrer header value of the current top level navigation. | |
109 const std::string& referrer() const { | |
110 return referrer_; | |
111 } | |
112 | |
113 void set_referrer(const std::string& referrer) { | |
114 referrer_ = referrer; | |
115 } | |
116 | |
117 // Return true if this is a URL that represents a top-level | |
118 // document that might have to be rendered in CF. | |
119 virtual bool IsTopLevelUrl(const wchar_t* url); | |
120 | |
121 // Called when we've detected the http-equiv meta tag in the current page | |
122 // and need to switch over from mshtml to CF. | |
123 virtual HRESULT NavigateToCurrentUrlInCF(IBrowserService* browser); | |
124 | |
125 void set_post_data(VARIANT* post_data) { | |
126 post_data_.Reset(); | |
127 if (post_data) { | |
128 if (V_VT(post_data) == (VT_BYREF | VT_VARIANT)) { | |
129 post_data_.Set(*post_data->pvarVal); | |
130 } else { | |
131 NOTREACHED() << "unexpected type for post_data: " | |
132 << std::hex << post_data->vt; | |
133 } | |
134 } | |
135 } | |
136 | |
137 const base::win::ScopedVariant& post_data() const { | |
138 return post_data_; | |
139 } | |
140 | |
141 void set_headers(VARIANT* headers) { | |
142 headers_.Reset(); | |
143 if (headers) { | |
144 headers_ = *headers; | |
145 } | |
146 } | |
147 | |
148 const base::win::ScopedVariant& headers() const { | |
149 return headers_; | |
150 } | |
151 | |
152 protected: | |
153 std::string referrer_; | |
154 std::wstring url_; | |
155 base::win::ScopedVariant post_data_; | |
156 base::win::ScopedVariant headers_; | |
157 | |
158 static base::LazyInstance<base::ThreadLocalPointer<NavigationManager> > | |
159 thread_singleton_; | |
160 | |
161 private: | |
162 DISALLOW_COPY_AND_ASSIGN(NavigationManager); | |
163 }; | |
164 | |
165 // static-only class that manages an IMoniker patch. | |
166 // We need this patch to stay in the loop when top-level HTML content is | |
167 // downloaded that might have the CF http-equiv meta tag. | |
168 // When we detect candidates for those requests, we add our own callback | |
169 // object (as explained at the top of this file) and use it to cache the | |
170 // original document contents in order to avoid multiple network trips | |
171 // if we need to switch the renderer over to CF. | |
172 class MonikerPatch { | |
173 MonikerPatch() {} // no instances should be created of this class. | |
174 public: | |
175 // Patches two IMoniker methods, BindToObject and BindToStorage. | |
176 static bool Initialize(); | |
177 | |
178 // Nullifies the IMoniker patches. | |
179 static void Uninitialize(); | |
180 | |
181 // Typedefs for IMoniker methods. | |
182 typedef HRESULT (STDMETHODCALLTYPE* IMoniker_BindToObject_Fn)(IMoniker* me, | |
183 IBindCtx* bind_ctx, IMoniker* to_left, REFIID iid, void** obj); | |
184 typedef HRESULT (STDMETHODCALLTYPE* IMoniker_BindToStorage_Fn)(IMoniker* me, | |
185 IBindCtx* bind_ctx, IMoniker* to_left, REFIID iid, void** obj); | |
186 | |
187 static STDMETHODIMP BindToObject(IMoniker_BindToObject_Fn original, | |
188 IMoniker* me, IBindCtx* bind_ctx, | |
189 IMoniker* to_left, REFIID iid, void** obj); | |
190 | |
191 static STDMETHODIMP BindToStorage(IMoniker_BindToStorage_Fn original, | |
192 IMoniker* me, IBindCtx* bind_ctx, | |
193 IMoniker* to_left, REFIID iid, void** obj); | |
194 }; | |
195 | |
196 extern wchar_t* kChromeRequestParam; | |
197 | |
198 #endif // CHROME_FRAME_URLMON_MONIKER_H_ | |
OLD | NEW |