diff options
author | amit@chromium.org <amit@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-04-14 00:35:52 +0000 |
---|---|---|
committer | amit@chromium.org <amit@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-04-14 00:35:52 +0000 |
commit | 3ee6112cc9d368ccd11d2cc2eea4f3aca2fd4400 (patch) | |
tree | f4b1f729762acbdd4ee3903f0b29d04f77b1b952 /chrome_frame/urlmon_moniker.cc | |
parent | 72eb2da638af5bcb4830827eeb1edebb580e36b1 (diff) | |
download | chromium_src-3ee6112cc9d368ccd11d2cc2eea4f3aca2fd4400.zip chromium_src-3ee6112cc9d368ccd11d2cc2eea4f3aca2fd4400.tar.gz chromium_src-3ee6112cc9d368ccd11d2cc2eea4f3aca2fd4400.tar.bz2 |
Fix for remaining major issues with moniker patch
This patch fixes things so that they now work 'naturally', i.e switch
to chrome frame looks just like switching to pdf. The same bind context
and underlying network transaction objects are used and requests aren't
sent multiple times. Finally the TestPostReissue test is happy!
This patch fixes two issues with earlier scheme:
Issue 1: data can be read only once from a given bind context. Mshtml
looks at the mime type in the FORMATETC but never issues a read. So when
it switches, the new active document can read from start. Since we are
reading the data for switching, when we actually switch, we have to
transfer over the data read so far to our UrlmonUrlRequest.
Issue 2: The very first UrlmomUrlRequest has to start binding right away,
in the context of BindToStorage or network transcations associated with
the bind context are gone (due to OnStopBinding for BindToObject).
TEST=covered by existing tests
BUG=33332
Review URL: http://codereview.chromium.org/1508033
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@44427 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome_frame/urlmon_moniker.cc')
-rw-r--r-- | chrome_frame/urlmon_moniker.cc | 62 |
1 files changed, 46 insertions, 16 deletions
diff --git a/chrome_frame/urlmon_moniker.cc b/chrome_frame/urlmon_moniker.cc index 49632fd..27b15df 100644 --- a/chrome_frame/urlmon_moniker.cc +++ b/chrome_frame/urlmon_moniker.cc @@ -15,7 +15,12 @@ static const int kMonikerBindToObject = 8; static const int kMonikerBindToStorage = kMonikerBindToObject + 1; -static wchar_t kBindContextParamName[] = L"_CHROMEFRAME_PRECREATE_"; + +// These are non const due to API expectations +static wchar_t* kBindContextCachedData = L"_CHROMEFRAME_PRECREATE_"; +static wchar_t* kBindToObjectBind = L"_CHROMEFRAME_BTO_BIND_"; +wchar_t* kChromeRequestParam = L"_CHROMEFRAME_REQUEST_"; + base::LazyInstance<base::ThreadLocalPointer<NavigationManager> > NavigationManager::thread_singleton_(base::LINKER_INITIALIZED); @@ -139,22 +144,18 @@ void NavigationManager::UnregisterThreadInstance() { } // Mark a bind context for navigation by storing a bind context param. -bool NavigationManager::SetForSwitch(IBindCtx* bind_context) { +bool NavigationManager::SetForSwitch(IBindCtx* bind_context, IStream* data) { if (!bind_context) { NOTREACHED(); return false; } - ScopedComPtr<IStream> dummy; - HRESULT hr = CreateStreamOnHGlobal(NULL, TRUE, dummy.Receive()); - if (dummy) { - hr = bind_context->RegisterObjectParam(kBindContextParamName, dummy); - } - + RewindStream(data); + HRESULT hr = bind_context->RegisterObjectParam(kBindContextCachedData, data); return SUCCEEDED(hr); } -bool NavigationManager::ResetSwitch(IBindCtx* bind_context) { +bool NavigationManager::IsSetToSwitch(IBindCtx* bind_context) { if (!bind_context) { NOTREACHED(); return false; @@ -162,13 +163,29 @@ bool NavigationManager::ResetSwitch(IBindCtx* bind_context) { ScopedComPtr<IUnknown> should_switch; HRESULT hr = E_FAIL; - hr = bind_context->GetObjectParam(kBindContextParamName, + hr = bind_context->GetObjectParam(kBindContextCachedData, should_switch.Receive()); - hr = bind_context->RevokeObjectParam(kBindContextParamName); - return !!should_switch; } +HRESULT NavigationManager::ResetSwitch(IBindCtx* bind_context, IStream** data) { + if (!bind_context) { + NOTREACHED(); + return false; + } + + ScopedComPtr<IUnknown> data_unknown; + HRESULT hr = E_FAIL; + hr = bind_context->GetObjectParam(kBindContextCachedData, + data_unknown.Receive()); + hr = bind_context->RevokeObjectParam(kBindContextCachedData); + if (data_unknown) { + hr = data_unknown.QueryInterface(data); + DCHECK(SUCCEEDED(hr)); + } + return hr; +} + ///////////////////////////////////////// // static @@ -211,8 +228,7 @@ bool ShouldWrapCallback(IMoniker* moniker, REFIID iid, IBindCtx* bind_context) { } ScopedComPtr<IUnknown> our_request; - hr = bind_context->GetObjectParam(L"_CHROMEFRAME_REQUEST_", - our_request.Receive()); + hr = bind_context->GetObjectParam(kChromeRequestParam, our_request.Receive()); if (our_request) { DLOG(INFO) << __FUNCTION__ << " Url: " << url << " Not wrapping: request from chrome frame."; @@ -243,7 +259,9 @@ HRESULT MonikerPatch::BindToObject(IMoniker_BindToObject_Fn original, DCHECK(to_left == NULL); HRESULT hr = S_OK; - if (NavigationManager::ResetSwitch(bind_ctx)) { + // Bind context is marked for switch when we sniff data in BSCBStorageBind + // and determine that the renderer to be used is Chrome. + if (NavigationManager::IsSetToSwitch(bind_ctx)) { // We could implement the BindToObject ourselves here but instead we // simply register Chrome Frame ActiveDoc as a handler for 'text/html' // in this bind context. This makes urlmon instantiate CF Active doc @@ -252,6 +270,13 @@ HRESULT MonikerPatch::BindToObject(IMoniker_BindToObject_Fn original, CLSID classes[] = { CLSID_ChromeActiveDocument }; hr = RegisterMediaTypeClass(bind_ctx, arraysize(media_types), media_types, classes, 0); + } else { + // In case the binding begins with BindToObject we do not need + // to cache the data in the sniffing code. + ScopedComPtr<IStream> no_cache; + CreateStreamOnHGlobal(NULL, TRUE, no_cache.Receive()); + if (no_cache) + bind_ctx->RegisterObjectParam(kBindToObjectBind, no_cache); } hr = original(me, bind_ctx, to_left, iid, obj); @@ -267,9 +292,14 @@ HRESULT MonikerPatch::BindToStorage(IMoniker_BindToStorage_Fn original, HRESULT hr = S_OK; CComObject<BSCBStorageBind>* callback = NULL; if (ShouldWrapCallback(me, iid, bind_ctx)) { + // Is this bind context marked as no cache by BindToObject already? + ScopedComPtr<IUnknown> no_cache; + if (bind_ctx) + bind_ctx->GetObjectParam(kBindToObjectBind, no_cache.Receive()); + hr = CComObject<BSCBStorageBind>::CreateInstance(&callback); callback->AddRef(); - hr = callback->Initialize(me, bind_ctx); + hr = callback->Initialize(me, bind_ctx, !!no_cache); DCHECK(SUCCEEDED(hr)); } |