diff options
-rw-r--r-- | chrome_frame/bho.cc | 181 | ||||
-rw-r--r-- | chrome_frame/bho.h | 10 | ||||
-rw-r--r-- | chrome_frame/extra_system_apis.h | 28 |
3 files changed, 83 insertions, 136 deletions
diff --git a/chrome_frame/bho.cc b/chrome_frame/bho.cc index 6802236..aee9282 100644 --- a/chrome_frame/bho.cc +++ b/chrome_frame/bho.cc @@ -50,6 +50,13 @@ _ATL_FUNC_INFO Bho::kBeforeNavigate2Info = { Bho::Bho() { } +HRESULT Bho::FinalConstruct() { + return S_OK; +} + +void Bho::FinalRelease() { +} + STDMETHODIMP Bho::SetSite(IUnknown* site) { HRESULT hr = S_OK; if (site) { @@ -122,11 +129,57 @@ STDMETHODIMP Bho::BeforeNavigate2(IDispatch* dispatch, VARIANT* url, return S_OK; } -HRESULT Bho::FinalConstruct() { - return S_OK; -} +HRESULT Bho::NavigateToCurrentUrlInCF(IBrowserService* browser) { + DCHECK(browser); + MarkBrowserOnThreadForCFNavigation(browser); + ScopedComPtr<IBindCtx> bind_context; + ScopedComPtr<IMoniker> moniker; + HRESULT hr = ::CreateBindCtx(0, bind_context.Receive()); + DCHECK(bind_context); + if (SUCCEEDED(hr) && + SUCCEEDED(hr = ::CreateURLMonikerEx(NULL, url_.c_str(), moniker.Receive(), + URL_MK_UNIFORM))) { + DCHECK(SUCCEEDED(hr)); + if (SUCCEEDED(hr)) { +#ifndef NDEBUG + // We've just created a new moniker for a URL that has just been fetched. + // However, the moniker used for the current navigation should still + // be running. + // The documentation for IMoniker::IsRunning() states that if the + // moniker is already running (i.e. an equal moniker already exists), + // then the return value from IsRunning will be S_OK (or 0) and + // S_FALSE (1) when the moniker is not running. + // http://msdn.microsoft.com/en-us/library/ms678475(VS.85).aspx + // However, knowing that the IsRunning implementation relies on + // the bind context and that the bind context uses ole32's + // IRunningObjectTable::IsRunning to do its bidding, the return value + // is actually TRUE (or 1) when the moniker is running and FALSE (0) + // when it is not running. Yup, the opposite of what you'd expect :-) + // http://msdn.microsoft.com/en-us/library/ms682169(VS.85).aspx + HRESULT running = moniker->IsRunning(bind_context, NULL, NULL); + DCHECK(running == TRUE) << "Moniker not already running?"; +#endif + + // If there's a referrer, preserve it. + std::wstring headers; + if (!referrer_.empty()) { + headers = StringPrintf(L"Referer: %ls\r\n\r\n", + ASCIIToWide(referrer_).c_str()); + } -void Bho::FinalRelease() { + // Pass in URL fragments if applicable. + std::wstring fragment; + GURL parsed_moniker_url(url_); + if (parsed_moniker_url.has_ref()) { + fragment = UTF8ToWide(parsed_moniker_url.ref()); + } + + hr = NavigateBrowserToMoniker(browser, moniker, headers.c_str(), + bind_context, fragment.c_str()); + } + } + + return hr; } namespace { @@ -173,26 +226,6 @@ bool DocumentHasEmbeddedItems(IUnknown* browser) { return has_embedded_items; } -HRESULT DeletePreviousNavigationEntry(IBrowserService* browser) { - DCHECK(browser); - - ScopedComPtr<ITravelLog> travel_log; - HRESULT hr = browser->GetTravelLog(travel_log.Receive()); - DCHECK(travel_log); - if (travel_log) { - ScopedComPtr<ITravelLogEx> travel_log_ex; - if (SUCCEEDED(hr = travel_log_ex.QueryFrom(travel_log)) || - SUCCEEDED(hr = travel_log.QueryInterface(__uuidof(IIEITravelLogEx), - reinterpret_cast<void**>(travel_log_ex.Receive())))) { - hr = travel_log_ex->DeleteIndexEntry(browser, -1); - } else { - NOTREACHED() << "ITravelLogEx"; - } - } - - return hr; -} - } // end namespace HRESULT Bho::OnHttpEquiv(IBrowserService_OnHttpEquiv_Fn original_httpequiv, @@ -206,83 +239,7 @@ HRESULT Bho::OnHttpEquiv(IBrowserService_OnHttpEquiv_Fn original_httpequiv, // being navigated to so we always have to wait for done to be TRUE // before re-initiating the navigation. - if (done) { - if (CheckForCFNavigation(browser, false)) { - // TODO(tommi): See if we can't figure out a cleaner way to avoid this. - // For small documents we can hit a problem here. When we attempt to - // navigate the document again in CF, mshtml can "complete" the current - // navigation (if all data is available) and fire off script events such - // as onload and even render the page. This will happen inside - // NavigateBrowserToMoniker below. - // To work around this, we clear the contents of the document before - // opening it up in CF. - ClearDocumentContents(browser); - - ScopedComPtr<IOleObject> mshtml_ole_object; - HRESULT hr = shell_view->GetItemObject(SVGIO_BACKGROUND, IID_IOleObject, - reinterpret_cast<void**>(mshtml_ole_object.Receive())); - DCHECK(FAILED(hr) || mshtml_ole_object != NULL); - if (mshtml_ole_object) { - ScopedComPtr<IMoniker> moniker; - hr = mshtml_ole_object->GetMoniker(OLEGETMONIKER_ONLYIFTHERE, - OLEWHICHMK_OBJFULL, moniker.Receive()); - DCHECK(FAILED(hr) || moniker != NULL); - if (moniker) { - DLOG(INFO) << "Navigating in CF"; - - ScopedComPtr<IBindCtx> bind_context; - // This bind context will be discarded by IE and a new one - // constructed, so it's OK to create a sync bind context. - ::CreateBindCtx(0, bind_context.Receive()); - - DCHECK(bind_context); - - // If there's a referrer, preserve it. - std::wstring headers; - // Pass in URL fragments if applicable. - std::wstring fragment; - - Bho* chrome_frame_bho = Bho::GetCurrentThreadBhoInstance(); - if (chrome_frame_bho) { - if (!chrome_frame_bho->referrer().empty()) { - headers = StringPrintf(L"Referer: %ls\r\n\r\n", - ASCIIToWide(chrome_frame_bho->referrer()).c_str()); - } - // If the original URL contains an anchor, then the URL queried - // from the moniker does not contain the anchor. To workaround - // this we retrieve the URL from our BHO. - std::wstring moniker_url = GetActualUrlFromMoniker( - moniker, NULL, chrome_frame_bho->url()); - - GURL parsed_moniker_url(moniker_url); - if (parsed_moniker_url.has_ref()) { - fragment = UTF8ToWide(parsed_moniker_url.ref()); - } - } - - hr = NavigateBrowserToMoniker(browser, moniker, headers.c_str(), - bind_context, fragment.c_str()); - - if (SUCCEEDED(hr)) { - // Now that we've reissued the request, we need to remove the - // original one from the travel log. - DeletePreviousNavigationEntry(browser); - } - } else { - DLOG(ERROR) << "Couldn't get the current moniker"; - } - } - - if (FAILED(hr)) { - NOTREACHED(); - // Lower the flag. - CheckForCFNavigation(browser, true); - } else { - // The navigate-in-gcf flag will be cleared in - // HttpNegotiatePatch::ReportProgress when the mime type is reported. - } - } - } else if (in_arg && VT_BSTR == V_VT(in_arg)) { + if (!done && in_arg && VT_BSTR == V_VT(in_arg)) { if (StrStrI(V_BSTR(in_arg), kChromeContentPrefix)) { // OnHttpEquiv is invoked for meta tags within sub frames as well. // We want to switch renderers only for the top level frame. @@ -291,8 +248,24 @@ HRESULT Bho::OnHttpEquiv(IBrowserService_OnHttpEquiv_Fn original_httpequiv, // notification is coming from those and not the top level document. // The embedded items should only be created once the top level // doc has been created. - if (!DocumentHasEmbeddedItems(browser)) - MarkBrowserOnThreadForCFNavigation(browser); + if (!DocumentHasEmbeddedItems(browser)) { + Bho* bho = Bho::GetCurrentThreadBhoInstance(); + DCHECK(bho); + DLOG(INFO) << "Found tag in page. Marking browser." << bho->url() << + StringPrintf(" tid=0x%08X", ::GetCurrentThreadId()); + if (bho) { + // TODO(tommi): See if we can't figure out a cleaner way to avoid + // this. For some documents we can hit a problem here. When we + // attempt to navigate the document again in CF, mshtml can "complete" + // the current navigation (if all data is available) and fire off + // script events such as onload and even render the page. + // This will happen inside NavigateBrowserToMoniker below. + // To work around this, we clear the contents of the document before + // opening it up in CF. + ClearDocumentContents(browser); + bho->NavigateToCurrentUrlInCF(browser); + } + } } } @@ -357,7 +330,7 @@ bool PatchHelper::InitializeAndPatchProtocolsIfNeeded() { HttpNegotiatePatch::Initialize(); - bool patch_protocol = GetConfigBool(true, kPatchProtocols); + bool patch_protocol = GetConfigBool(false, kPatchProtocols); if (patch_protocol) { ProtocolSinkWrap::PatchProtocolHandlers(); state_ = PATCH_PROTOCOL; diff --git a/chrome_frame/bho.h b/chrome_frame/bho.h index 54bdc99..9c058ff 100644 --- a/chrome_frame/bho.h +++ b/chrome_frame/bho.h @@ -5,8 +5,6 @@ #ifndef CHROME_FRAME_BHO_H_ #define CHROME_FRAME_BHO_H_ -#include <string> - #include <atlbase.h> #include <atlcom.h> #include <exdisp.h> @@ -14,6 +12,8 @@ #include <mshtml.h> #include <shdeprecated.h> +#include <string> + #include "base/lazy_instance.h" #include "base/thread_local.h" #include "chrome_tab.h" // NOLINT @@ -62,8 +62,8 @@ BEGIN_COM_MAP(Bho) END_COM_MAP() BEGIN_SINK_MAP(Bho) - SINK_ENTRY_INFO(0, DIID_DWebBrowserEvents2, DISPID_BEFORENAVIGATE2, - BeforeNavigate2, &kBeforeNavigate2Info) + SINK_ENTRY_INFO(0, DIID_DWebBrowserEvents2, DISPID_BEFORENAVIGATE2, + BeforeNavigate2, &kBeforeNavigate2Info) END_SINK_MAP() // Lifetime management methods @@ -78,6 +78,8 @@ END_SINK_MAP() VARIANT* target_frame_name, VARIANT* post_data, VARIANT* headers, VARIANT_BOOL* cancel); + HRESULT NavigateToCurrentUrlInCF(IBrowserService* browser); + // mshtml sends an IOleCommandTarget::Exec of OLECMDID_HTTPEQUIV // (and OLECMDID_HTTPEQUIV_DONE) as soon as it parses a meta tag. // It also sends contents of the meta tag as an argument. IEFrame diff --git a/chrome_frame/extra_system_apis.h b/chrome_frame/extra_system_apis.h index 765c5b2..93aad26 100644 --- a/chrome_frame/extra_system_apis.h +++ b/chrome_frame/extra_system_apis.h @@ -84,34 +84,6 @@ IDocObjectService : public IUnknown { STDMETHOD(IsErrorUrl)(LPCTSTR url, BOOL* is_error) = 0; }; -// Travel log interface that supports deleting entries from the travel log. -// See for more details: -// http://msdn.microsoft.com/en-us/library/aa511272.aspx -// http://www.geoffchappell.com/viewer.htm?doc=studies/windows/ie/shdocvw/interfaces/tlog/itravellogex/createenumentry.htm -// It seems that in IE8 the interface name was changed to IIEITravelLogEx. -interface __declspec(uuid("3050F679-98B5-11CF-BB82-00AA00BDCE0B")) -ITravelLogEx : public IUnknown { - STDMETHOD(FindTravelEntryWithUrl)(IUnknown* unk, UINT code_page, - const wchar_t* url, - ITravelEntry** entry) = 0; - STDMETHOD(TravelToUrl)(IUnknown* unk, UINT code_page, const wchar_t* url) = 0; - STDMETHOD(DeleteIndexEntry)(IUnknown* unk, int offset) = 0; - STDMETHOD(DeleteUrlEntry)(IUnknown* unk, UINT code_page, - const wchar_t* url) = 0; - STDMETHOD(CountEntryNodes)(IUnknown* unk, DWORD flags, DWORD* count) = 0; - STDMETHOD(CreateEnumEntry)(IUnknown* unk, IEnumTravelLogEntry** entry_enum, - DWORD flags) = 0; - STDMETHOD(DeleteEntry)(IUnknown* unk, ITravelLogEntry* entry) = 0; - STDMETHOD(InsertEntry)(IUnknown* unk_relative_to, - ITravelLogEntry* entry_relative_to, BOOL prepend, - IUnknown* unk, ITravelLogEntry** entry) = 0; - STDMETHOD(TravelToEntry)(IUnknown* unk, ITravelLogEntry* entry) = 0; -}; - -interface __declspec(uuid("DD9E2B32-4D78-44F1-B59B-8CA4C9392140")) -IIEITravelLogEx : public ITravelLogEx { -}; - // Flags for ITravelLogEx::CountEntryNodes, CreateEnumEntry. #define TLEF_RELATIVE_INCLUDE_CURRENT (0x01) // count the current entry #define TLEF_RELATIVE_BACK (0x10) // count backward entries |