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

Side by Side Diff: chrome_frame/bho.cc

Issue 218019: Initial import of the Chrome Frame codebase. Integration in chrome.gyp coming... (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 11 years, 2 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « chrome_frame/bho.h ('k') | chrome_frame/bho.rgs » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2009 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 #include "chrome_frame/bho.h"
6
7 #include <shlguid.h>
8 #include <shobjidl.h>
9
10 #include "base/logging.h"
11 #include "base/registry.h"
12 #include "base/scoped_bstr_win.h"
13 #include "base/scoped_comptr_win.h"
14 #include "base/scoped_variant_win.h"
15 #include "base/string_util.h"
16 #include "chrome_tab.h" // NOLINT
17 #include "chrome_frame/protocol_sink_wrap.h"
18 #include "chrome_frame/utils.h"
19 #include "chrome_frame/vtable_patch_manager.h"
20
21 const wchar_t kUrlMonDllName[] = L"urlmon.dll";
22 const wchar_t kPatchProtocols[] = L"PatchProtocols";
23 static const int kIBrowserServiceOnHttpEquivIndex = 30;
24
25 PatchHelper g_patch_helper;
26
27 BEGIN_VTABLE_PATCHES(IBrowserService)
28 VTABLE_PATCH_ENTRY(kIBrowserServiceOnHttpEquivIndex, Bho::OnHttpEquiv)
29 END_VTABLE_PATCHES()
30
31 _ATL_FUNC_INFO Bho::kBeforeNavigate2Info = {
32 CC_STDCALL, VT_EMPTY, 7, {
33 VT_DISPATCH,
34 VT_VARIANT | VT_BYREF,
35 VT_VARIANT | VT_BYREF,
36 VT_VARIANT | VT_BYREF,
37 VT_VARIANT | VT_BYREF,
38 VT_VARIANT | VT_BYREF,
39 VT_BOOL | VT_BYREF
40 }
41 };
42
43 Bho::Bho() {
44 }
45
46 STDMETHODIMP Bho::SetSite(IUnknown* site) {
47 HRESULT hr = S_OK;
48 if (site) {
49 ScopedComPtr<IWebBrowser2> web_browser2;
50 web_browser2.QueryFrom(site);
51 if (web_browser2) {
52 hr = DispEventAdvise(web_browser2, &DIID_DWebBrowserEvents2);
53 DCHECK(SUCCEEDED(hr)) << "DispEventAdvise failed. Error: " << hr;
54 }
55
56 if (g_patch_helper.state() == PatchHelper::PATCH_IBROWSER) {
57 ScopedComPtr<IBrowserService> browser_service;
58 hr = DoQueryService(SID_SShellBrowser, site, browser_service.Receive());
59 DCHECK(browser_service) << "DoQueryService - SID_SShellBrowser failed."
60 << " Site: " << site << " Error: " << hr;
61 if (browser_service) {
62 g_patch_helper.PatchBrowserService(browser_service);
63 DCHECK(SUCCEEDED(hr)) << "vtable_patch::PatchInterfaceMethods failed."
64 << " Site: " << site << " Error: " << hr;
65 }
66 }
67 }
68
69 return IObjectWithSiteImpl<Bho>::SetSite(site);
70 }
71
72 STDMETHODIMP Bho::BeforeNavigate2(IDispatch* dispatch, VARIANT* url,
73 VARIANT* flags, VARIANT* target_frame_name, VARIANT* post_data,
74 VARIANT* headers, VARIANT_BOOL* cancel) {
75 ScopedComPtr<IWebBrowser2> web_browser2;
76 if (dispatch)
77 web_browser2.QueryFrom(dispatch);
78
79 if (!web_browser2) {
80 NOTREACHED() << "Can't find WebBrowser2 with given dispatch";
81 return S_OK; // Return success, we operate on best effort basis.
82 }
83
84 DLOG(INFO) << "BeforeNavigate2: " << url->bstrVal;
85
86 if (g_patch_helper.state() == PatchHelper::PATCH_IBROWSER) {
87 VARIANT_BOOL is_top_level = VARIANT_FALSE;
88 web_browser2->get_TopLevelContainer(&is_top_level);
89
90 std::wstring current_url;
91 bool is_chrome_protocol = false;
92 if (is_top_level && IsValidUrlScheme(url->bstrVal)) {
93 current_url.assign(url->bstrVal, SysStringLen(url->bstrVal));
94 is_chrome_protocol = StartsWith(current_url, kChromeProtocolPrefix,
95 false);
96
97 if (!is_chrome_protocol && IsOptInUrl(current_url.c_str())) {
98 DLOG(INFO) << "Canceling navigation and switching to cf";
99 // Cancel original navigation
100 *cancel = VARIANT_TRUE;
101
102 // Issue new request with 'cf:'
103 current_url.insert(0, kChromeProtocolPrefix);
104 ScopedVariant new_url(current_url.c_str());
105 HRESULT hr = web_browser2->Navigate2(new_url.AsInput(), flags,
106 target_frame_name, post_data,
107 headers);
108 DCHECK(SUCCEEDED(hr)) << "web_browser2->Navigate2 failed. Error: " << hr
109 << std::endl << "Url: " << current_url
110 << std::endl << "flags: " << flags
111 << std::endl << "post data: " << post_data
112 << std::endl << "headers: " << headers;
113 }
114 }
115 }
116 return S_OK;
117 }
118
119 HRESULT Bho::FinalConstruct() {
120 return S_OK;
121 }
122
123 void Bho::FinalRelease() {
124 }
125
126 HRESULT STDMETHODCALLTYPE Bho::OnHttpEquiv(
127 IBrowserService_OnHttpEquiv_Fn original_httpequiv,
128 IBrowserService* browser, IShellView* shell_view, BOOL done,
129 VARIANT* in_arg, VARIANT* out_arg) {
130 if (!done && in_arg && (VT_BSTR == V_VT(in_arg))) {
131 if (StrStrI(V_BSTR(in_arg), kChromeContentPrefix)) {
132 // OnHttpEquiv is invoked for meta tags within sub frames as well.
133 // We want to switch renderers only for the top level frame. Since
134 // the same |browser| and |shell_view| are passed in to OnHttpEquiv
135 // even for sub iframes, we determine if this is the top one by
136 // checking if there are any sub frames created or not.
137 ScopedComPtr<IWebBrowser2> web_browser2;
138 DoQueryService(SID_SWebBrowserApp, browser, web_browser2.Receive());
139 if (web_browser2 && !HasSubFrames(web_browser2))
140 SwitchRenderer(web_browser2, browser, shell_view, V_BSTR(in_arg));
141 }
142 }
143
144 return original_httpequiv(browser, shell_view, done, in_arg, out_arg);
145 }
146
147 bool Bho::HasSubFrames(IWebBrowser2* web_browser2) {
148 bool has_sub_frames = false;
149 ScopedComPtr<IDispatch> doc_dispatch;
150 if (web_browser2) {
151 HRESULT hr = web_browser2->get_Document(doc_dispatch.Receive());
152 DCHECK(SUCCEEDED(hr) && doc_dispatch) <<
153 "web_browser2->get_Document failed. Error: " << hr;
154 ScopedComPtr<IOleContainer> container;
155 if (SUCCEEDED(hr) && doc_dispatch) {
156 container.QueryFrom(doc_dispatch);
157 ScopedComPtr<IEnumUnknown> enumerator;
158 if (container) {
159 container->EnumObjects(OLECONTF_EMBEDDINGS, enumerator.Receive());
160 ScopedComPtr<IUnknown> unk;
161 ULONG items_retrieved = 0;
162 if (enumerator)
163 enumerator->Next(1, unk.Receive(), &items_retrieved);
164 has_sub_frames = (items_retrieved != 0);
165 }
166 }
167 }
168
169 return has_sub_frames;
170 }
171
172 HRESULT Bho::SwitchRenderer(IWebBrowser2* web_browser2,
173 IBrowserService* browser, IShellView* shell_view,
174 const wchar_t* meta_tag) {
175 DCHECK(web_browser2 && browser && shell_view && meta_tag);
176
177 // Get access to the mshtml instance and the moniker
178 ScopedComPtr<IOleObject> mshtml_ole_object;
179 HRESULT hr = shell_view->GetItemObject(SVGIO_BACKGROUND, IID_IOleObject,
180 reinterpret_cast<void**>(mshtml_ole_object.Receive()));
181 if (!mshtml_ole_object) {
182 NOTREACHED() << "shell_view->GetItemObject failed. Error: " << hr;
183 return hr;
184 }
185
186 std::wstring url;
187 ScopedComPtr<IMoniker> moniker;
188 hr = mshtml_ole_object->GetMoniker(OLEGETMONIKER_ONLYIFTHERE,
189 OLEWHICHMK_OBJFULL, moniker.Receive());
190 DCHECK(moniker) << "mshtml_ole_object->GetMoniker failed. Error: " << hr;
191
192 if (moniker)
193 hr = GetUrlFromMoniker(moniker, NULL, &url);
194
195 DCHECK(!url.empty()) << "GetUrlFromMoniker failed. Error: " << hr;
196 DCHECK(!StartsWith(url, kChromeProtocolPrefix, false));
197
198 if (!url.empty()) {
199 url.insert(0, kChromeProtocolPrefix);
200 // Navigate to new url
201 VARIANT empty = ScopedVariant::kEmptyVariant;
202 VARIANT flags = { VT_I4 };
203 V_I4(&flags) = 0;
204 ScopedVariant url_var(url.c_str());
205 hr = web_browser2->Navigate2(url_var.AsInput(), &flags, &empty, &empty,
206 &empty);
207 DCHECK(SUCCEEDED(hr)) << "web_browser2->Navigate2 failed. Error: " << hr
208 << std::endl << "Url: " << url;
209 }
210
211 return S_OK;
212 }
213
214 void PatchHelper::InitializeAndPatchProtocolsIfNeeded() {
215 if (state_ != UNKNOWN)
216 return;
217
218 bool patch_protocol = GetConfigBool(true, kPatchProtocols);
219 if (patch_protocol) {
220 ProtocolSinkWrap::PatchProtocolHandler(kUrlMonDllName, CLSID_HttpProtocol);
221 ProtocolSinkWrap::PatchProtocolHandler(kUrlMonDllName, CLSID_HttpSProtocol);
222 state_ = PATCH_PROTOCOL;
223 } else {
224 state_ = PATCH_IBROWSER;
225 }
226 }
227
228 void PatchHelper::PatchBrowserService(IBrowserService* browser_service) {
229 DCHECK(state_ == PATCH_IBROWSER);
230 state_ = PATCH_IBROWSER_OK;
231 vtable_patch::PatchInterfaceMethods(browser_service,
232 IBrowserService_PatchInfo);
233 }
234
235 extern vtable_patch::MethodPatchInfo IInternetProtocol_PatchInfo[];
236 extern vtable_patch::MethodPatchInfo IInternetProtocolEx_PatchInfo[];
237 void PatchHelper::UnpatchIfNeeded() {
238 if (state_ == PATCH_PROTOCOL) {
239 vtable_patch::UnpatchInterfaceMethods(IInternetProtocol_PatchInfo);
240 vtable_patch::UnpatchInterfaceMethods(IInternetProtocolEx_PatchInfo);
241 } else if (state_ == PATCH_IBROWSER_OK) {
242 vtable_patch::UnpatchInterfaceMethods(IBrowserService_PatchInfo);
243 }
244
245 state_ = UNKNOWN;
246 }
247
OLDNEW
« no previous file with comments | « chrome_frame/bho.h ('k') | chrome_frame/bho.rgs » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698