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

Side by Side Diff: chrome_frame/protocol_sink_wrap.cc

Issue 3051018: Ensure that window.open requests issued by ChromeFrame carry the correct cook... (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: '' Created 10 years, 4 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/protocol_sink_wrap.h ('k') | chrome_frame/test/util_unittests.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include <htiframe.h> 5 #include <htiframe.h>
6 #include <mshtml.h> 6 #include <mshtml.h>
7 7
8 #include "chrome_frame/protocol_sink_wrap.h" 8 #include "chrome_frame/protocol_sink_wrap.h"
9 9
10 #include "base/logging.h" 10 #include "base/logging.h"
11 #include "base/registry.h" 11 #include "base/registry.h"
12 #include "base/scoped_bstr_win.h" 12 #include "base/scoped_bstr_win.h"
13 #include "base/singleton.h" 13 #include "base/singleton.h"
14 #include "base/string_util.h" 14 #include "base/string_util.h"
15 15
16 #include "chrome_frame/bho.h"
16 #include "chrome_frame/bind_context_info.h" 17 #include "chrome_frame/bind_context_info.h"
17 #include "chrome_frame/function_stub.h" 18 #include "chrome_frame/function_stub.h"
18 #include "chrome_frame/utils.h" 19 #include "chrome_frame/utils.h"
19 20
20 // BINDSTATUS_SERVER_MIMETYPEAVAILABLE == 54. Introduced in IE 8, so 21 // BINDSTATUS_SERVER_MIMETYPEAVAILABLE == 54. Introduced in IE 8, so
21 // not in everyone's headers yet. See: 22 // not in everyone's headers yet. See:
22 // http://msdn.microsoft.com/en-us/library/ms775133(VS.85,loband).aspx 23 // http://msdn.microsoft.com/en-us/library/ms775133(VS.85,loband).aspx
23 #ifndef BINDSTATUS_SERVER_MIMETYPEAVAILABLE 24 #ifndef BINDSTATUS_SERVER_MIMETYPEAVAILABLE
24 #define BINDSTATUS_SERVER_MIMETYPEAVAILABLE 54 25 #define BINDSTATUS_SERVER_MIMETYPEAVAILABLE 54
25 #endif 26 #endif
26 27
27 static const char kTextHtmlMimeType[] = "text/html"; 28 static const char kTextHtmlMimeType[] = "text/html";
28 const wchar_t kUrlMonDllName[] = L"urlmon.dll"; 29 const wchar_t kUrlMonDllName[] = L"urlmon.dll";
29 30
30 static const int kInternetProtocolStartIndex = 3; 31 static const int kInternetProtocolStartIndex = 3;
31 static const int kInternetProtocolReadIndex = 9; 32 static const int kInternetProtocolReadIndex = 9;
32 static const int kInternetProtocolStartExIndex = 13; 33 static const int kInternetProtocolStartExIndex = 13;
34 static const int kInternetProtocolLockRequestIndex = 11;
35 static const int kInternetProtocolUnlockRequestIndex = 12;
33 36
34 37
35 // IInternetProtocol/Ex patches. 38 // IInternetProtocol/Ex patches.
36 STDMETHODIMP Hook_Start(InternetProtocol_Start_Fn orig_start, 39 STDMETHODIMP Hook_Start(InternetProtocol_Start_Fn orig_start,
37 IInternetProtocol* protocol, 40 IInternetProtocol* protocol,
38 LPCWSTR url, 41 LPCWSTR url,
39 IInternetProtocolSink* prot_sink, 42 IInternetProtocolSink* prot_sink,
40 IInternetBindInfo* bind_info, 43 IInternetBindInfo* bind_info,
41 DWORD flags, 44 DWORD flags,
42 HANDLE_PTR reserved); 45 HANDLE_PTR reserved);
43 46
44 STDMETHODIMP Hook_StartEx(InternetProtocol_StartEx_Fn orig_start_ex, 47 STDMETHODIMP Hook_StartEx(InternetProtocol_StartEx_Fn orig_start_ex,
45 IInternetProtocolEx* protocol, 48 IInternetProtocolEx* protocol,
46 IUri* uri, 49 IUri* uri,
47 IInternetProtocolSink* prot_sink, 50 IInternetProtocolSink* prot_sink,
48 IInternetBindInfo* bind_info, 51 IInternetBindInfo* bind_info,
49 DWORD flags, 52 DWORD flags,
50 HANDLE_PTR reserved); 53 HANDLE_PTR reserved);
51 54
52 STDMETHODIMP Hook_Read(InternetProtocol_Read_Fn orig_read, 55 STDMETHODIMP Hook_Read(InternetProtocol_Read_Fn orig_read,
53 IInternetProtocol* protocol, 56 IInternetProtocol* protocol,
54 void* buffer, 57 void* buffer,
55 ULONG size, 58 ULONG size,
56 ULONG* size_read); 59 ULONG* size_read);
57 60
61 STDMETHODIMP Hook_LockRequest(InternetProtocol_LockRequest_Fn orig_req,
62 IInternetProtocol* protocol, DWORD dwOptions);
63
64 STDMETHODIMP Hook_UnlockRequest(InternetProtocol_UnlockRequest_Fn orig_req,
65 IInternetProtocol* protocol);
66
58 ///////////////////////////////////////////////////////////////////////////// 67 /////////////////////////////////////////////////////////////////////////////
59 BEGIN_VTABLE_PATCHES(CTransaction) 68 BEGIN_VTABLE_PATCHES(CTransaction)
60 VTABLE_PATCH_ENTRY(kInternetProtocolStartIndex, Hook_Start) 69 VTABLE_PATCH_ENTRY(kInternetProtocolStartIndex, Hook_Start)
61 VTABLE_PATCH_ENTRY(kInternetProtocolReadIndex, Hook_Read) 70 VTABLE_PATCH_ENTRY(kInternetProtocolReadIndex, Hook_Read)
71 VTABLE_PATCH_ENTRY(kInternetProtocolLockRequestIndex, Hook_LockRequest)
72 VTABLE_PATCH_ENTRY(kInternetProtocolUnlockRequestIndex, Hook_UnlockRequest)
62 END_VTABLE_PATCHES() 73 END_VTABLE_PATCHES()
63 74
64 BEGIN_VTABLE_PATCHES(CTransaction2) 75 BEGIN_VTABLE_PATCHES(CTransaction2)
65 VTABLE_PATCH_ENTRY(kInternetProtocolStartExIndex, Hook_StartEx) 76 VTABLE_PATCH_ENTRY(kInternetProtocolStartExIndex, Hook_StartEx)
66 END_VTABLE_PATCHES() 77 END_VTABLE_PATCHES()
67 78
68 // 79 //
69 // ProtocolSinkWrap implementation 80 // ProtocolSinkWrap implementation
70 81
71 // Static map initialization 82 // Static map initialization
(...skipping 423 matching lines...) Expand 10 before | Expand all | Expand 10 after
495 << suggested_mime_type_; 506 << suggested_mime_type_;
496 delegate->ReportProgress(BINDSTATUS_MIMETYPEAVAILABLE, 507 delegate->ReportProgress(BINDSTATUS_MIMETYPEAVAILABLE,
497 suggested_mime_type_); 508 suggested_mime_type_);
498 } 509 }
499 } 510 }
500 511
501 void ProtData::SaveReferrer(IInternetProtocolSink* delegate) { 512 void ProtData::SaveReferrer(IInternetProtocolSink* delegate) {
502 DCHECK_EQ(CHROME, renderer_type_); 513 DCHECK_EQ(CHROME, renderer_type_);
503 ScopedComPtr<IWinInetHttpInfo> info; 514 ScopedComPtr<IWinInetHttpInfo> info;
504 info.QueryFrom(delegate); 515 info.QueryFrom(delegate);
505 DCHECK(info);
506 if (info) { 516 if (info) {
507 char buffer[4096] = {0}; 517 char buffer[4096] = {0};
508 DWORD len = sizeof(buffer); 518 DWORD len = sizeof(buffer);
509 DWORD flags = 0; 519 DWORD flags = 0;
510 HRESULT hr = info->QueryInfo( 520 HRESULT hr = info->QueryInfo(
511 HTTP_QUERY_REFERER | HTTP_QUERY_FLAG_REQUEST_HEADERS, 521 HTTP_QUERY_REFERER | HTTP_QUERY_FLAG_REQUEST_HEADERS,
512 buffer, &len, &flags, 0); 522 buffer, &len, &flags, 0);
513 if (hr == S_OK && len > 0) 523 if (hr == S_OK && len > 0)
514 referrer_.assign(buffer); 524 referrer_.assign(buffer);
525 } else {
526 DLOG(WARNING) << "Failed to QI for IWinInetHttpInfo";
515 } 527 }
516 } 528 }
517 529
518 scoped_refptr<ProtData> ProtData::DataFromProtocol( 530 scoped_refptr<ProtData> ProtData::DataFromProtocol(
519 IInternetProtocol* protocol) { 531 IInternetProtocol* protocol) {
520 scoped_refptr<ProtData> instance; 532 scoped_refptr<ProtData> instance;
521 AutoLock lock(datamap_lock_); 533 AutoLock lock(datamap_lock_);
522 ProtocolDataMap::iterator it = datamap_.find(protocol); 534 ProtocolDataMap::iterator it = datamap_.find(protocol);
523 if (datamap_.end() != it) 535 if (datamap_.end() != it)
524 instance = it->second; 536 instance = it->second;
525 return instance; 537 return instance;
526 } 538 }
527 539
540 // This function looks for the url pattern indicating that this request needs
541 // to be forced into chrome frame.
542 // This hack is required because window.open requests from Chrome don't have
543 // the URL up front. The URL comes in much later when the renderer initiates a
544 // top level navigation for the url passed into window.open.
545 // The new page must be rendered in ChromeFrame to preserve the opener
546 // relationship with its parent even if the new page does not have the chrome
547 // meta tag.
548 bool HandleAttachToExistingExternalTab(LPCWSTR url,
549 IInternetProtocol* protocol,
550 IInternetProtocolSink* prot_sink,
551 IBindCtx* bind_ctx) {
552 if (MatchPatternWide(url, kChromeFrameAttachTabPattern)) {
553 scoped_refptr<ProtData> prot_data = ProtData::DataFromProtocol(protocol);
554 if (!prot_data) {
555 // Pass NULL as the read function which indicates that always return EOF
556 // without calling the underlying protocol.
557 prot_data = new ProtData(protocol, NULL, url);
558 PutProtData(bind_ctx, prot_data);
559 }
560
561 prot_sink->ReportProgress(BINDSTATUS_MIMETYPEAVAILABLE, kChromeMimeType);
562
563 int data_flags = BSCF_FIRSTDATANOTIFICATION | BSCF_LASTDATANOTIFICATION;
564 prot_sink->ReportData(data_flags, 0, 0);
565
566 prot_sink->ReportResult(S_OK, 0, NULL);
567 return true;
568 }
569 return false;
570 }
571
528 // IInternetProtocol/Ex hooks. 572 // IInternetProtocol/Ex hooks.
529 STDMETHODIMP Hook_Start(InternetProtocol_Start_Fn orig_start, 573 STDMETHODIMP Hook_Start(InternetProtocol_Start_Fn orig_start,
530 IInternetProtocol* protocol, LPCWSTR url, IInternetProtocolSink* prot_sink, 574 IInternetProtocol* protocol, LPCWSTR url, IInternetProtocolSink* prot_sink,
531 IInternetBindInfo* bind_info, DWORD flags, HANDLE_PTR reserved) { 575 IInternetBindInfo* bind_info, DWORD flags, HANDLE_PTR reserved) {
532 DCHECK(orig_start); 576 DCHECK(orig_start);
533 if (!url || !prot_sink || !bind_info) 577 if (!url || !prot_sink || !bind_info)
534 return E_INVALIDARG; 578 return E_INVALIDARG;
535 DLOG_IF(INFO, url != NULL) << "OnStart: " << url << PiFlags2Str(flags); 579 DLOG_IF(INFO, url != NULL) << "OnStart: " << url << PiFlags2Str(flags);
536 580
537 ScopedComPtr<IBindCtx> bind_ctx = BindCtxFromIBindInfo(bind_info); 581 ScopedComPtr<IBindCtx> bind_ctx = BindCtxFromIBindInfo(bind_info);
538 if (!bind_ctx) { 582 if (!bind_ctx) {
539 // MSHTML sometimes takes a short path, skips the creation of 583 // MSHTML sometimes takes a short path, skips the creation of
540 // moniker and binding, by directly grabbing protocol from InternetSession 584 // moniker and binding, by directly grabbing protocol from InternetSession
541 DLOG(INFO) << "DirectBind for " << url; 585 DLOG(INFO) << "DirectBind for " << url;
542 return orig_start(protocol, url, prot_sink, bind_info, flags, reserved); 586 return orig_start(protocol, url, prot_sink, bind_info, flags, reserved);
543 } 587 }
544 588
589 if (HandleAttachToExistingExternalTab(url, protocol, prot_sink, bind_ctx)) {
590 return S_OK;
591 }
592
545 if (IsCFRequest(bind_ctx)) { 593 if (IsCFRequest(bind_ctx)) {
546 return orig_start(protocol, url, prot_sink, bind_info, flags, reserved); 594 return orig_start(protocol, url, prot_sink, bind_info, flags, reserved);
547 } 595 }
548 596
549 scoped_refptr<ProtData> prot_data = ProtData::DataFromProtocol(protocol); 597 scoped_refptr<ProtData> prot_data = ProtData::DataFromProtocol(protocol);
550 if (prot_data) { 598 if (prot_data) {
551 DLOG(INFO) << "Found existing ProtData!"; 599 DLOG(INFO) << "Found existing ProtData!";
552 prot_data->UpdateUrl(url); 600 prot_data->UpdateUrl(url);
553 ScopedComPtr<IInternetProtocolSink> new_sink = 601 ScopedComPtr<IInternetProtocolSink> new_sink =
554 ProtocolSinkWrap::CreateNewSink(prot_sink, prot_data); 602 ProtocolSinkWrap::CreateNewSink(prot_sink, prot_data);
(...skipping 27 matching lines...) Expand all
582 DLOG_IF(INFO, url != NULL) << "OnStartEx: " << url << PiFlags2Str(flags); 630 DLOG_IF(INFO, url != NULL) << "OnStartEx: " << url << PiFlags2Str(flags);
583 631
584 ScopedComPtr<IBindCtx> bind_ctx = BindCtxFromIBindInfo(bind_info); 632 ScopedComPtr<IBindCtx> bind_ctx = BindCtxFromIBindInfo(bind_info);
585 if (!bind_ctx) { 633 if (!bind_ctx) {
586 // MSHTML sometimes takes a short path, skips the creation of 634 // MSHTML sometimes takes a short path, skips the creation of
587 // moniker and binding, by directly grabbing protocol from InternetSession. 635 // moniker and binding, by directly grabbing protocol from InternetSession.
588 DLOG(INFO) << "DirectBind for " << url; 636 DLOG(INFO) << "DirectBind for " << url;
589 return orig_start_ex(protocol, uri, prot_sink, bind_info, flags, reserved); 637 return orig_start_ex(protocol, uri, prot_sink, bind_info, flags, reserved);
590 } 638 }
591 639
640 if (HandleAttachToExistingExternalTab(url, protocol, prot_sink, bind_ctx)) {
641 return S_OK;
642 }
643
592 if (IsCFRequest(bind_ctx)) { 644 if (IsCFRequest(bind_ctx)) {
593 return orig_start_ex(protocol, uri, prot_sink, bind_info, flags, reserved); 645 return orig_start_ex(protocol, uri, prot_sink, bind_info, flags, reserved);
594 } 646 }
595 647
596 scoped_refptr<ProtData> prot_data = ProtData::DataFromProtocol(protocol); 648 scoped_refptr<ProtData> prot_data = ProtData::DataFromProtocol(protocol);
597 if (prot_data) { 649 if (prot_data) {
598 DLOG(INFO) << "Found existing ProtData!"; 650 DLOG(INFO) << "Found existing ProtData!";
599 prot_data->UpdateUrl(url); 651 prot_data->UpdateUrl(url);
600 ScopedComPtr<IInternetProtocolSink> new_sink = 652 ScopedComPtr<IInternetProtocolSink> new_sink =
601 ProtocolSinkWrap::CreateNewSink(prot_sink, prot_data); 653 ProtocolSinkWrap::CreateNewSink(prot_sink, prot_data);
(...skipping 11 matching lines...) Expand all
613 PutProtData(bind_ctx, prot_data); 665 PutProtData(bind_ctx, prot_data);
614 666
615 ScopedComPtr<IInternetProtocolSink> new_sink = 667 ScopedComPtr<IInternetProtocolSink> new_sink =
616 ProtocolSinkWrap::CreateNewSink(prot_sink, prot_data); 668 ProtocolSinkWrap::CreateNewSink(prot_sink, prot_data);
617 return orig_start_ex(protocol, uri, new_sink, bind_info, flags, reserved); 669 return orig_start_ex(protocol, uri, new_sink, bind_info, flags, reserved);
618 } 670 }
619 671
620 STDMETHODIMP Hook_Read(InternetProtocol_Read_Fn orig_read, 672 STDMETHODIMP Hook_Read(InternetProtocol_Read_Fn orig_read,
621 IInternetProtocol* protocol, void* buffer, ULONG size, ULONG* size_read) { 673 IInternetProtocol* protocol, void* buffer, ULONG size, ULONG* size_read) {
622 DCHECK(orig_read); 674 DCHECK(orig_read);
675 HRESULT hr = E_FAIL;
676
623 scoped_refptr<ProtData> prot_data = ProtData::DataFromProtocol(protocol); 677 scoped_refptr<ProtData> prot_data = ProtData::DataFromProtocol(protocol);
624 if (!prot_data) { 678 if (!prot_data) {
625 return orig_read(protocol, buffer, size, size_read); 679 hr = orig_read(protocol, buffer, size, size_read);
680 return hr;
626 } 681 }
627 682
628 HRESULT hr = prot_data->Read(buffer, size, size_read); 683 if (prot_data->is_attach_external_tab_request()) {
684 // return EOF always.
685 if (size_read)
686 *size_read = 0;
687 return S_FALSE;
688 }
689
690 hr = prot_data->Read(buffer, size, size_read);
629 return hr; 691 return hr;
630 } 692 }
631 693
694 STDMETHODIMP Hook_LockRequest(InternetProtocol_LockRequest_Fn orig_req,
695 IInternetProtocol* protocol, DWORD options) {
696 DCHECK(orig_req);
697
698 scoped_refptr<ProtData> prot_data = ProtData::DataFromProtocol(protocol);
699 if (prot_data && prot_data->is_attach_external_tab_request()) {
700 prot_data->AddRef();
701 return S_OK;
702 }
703
704 return orig_req(protocol, options);
705 }
706
707 STDMETHODIMP Hook_UnlockRequest(InternetProtocol_UnlockRequest_Fn orig_req,
708 IInternetProtocol* protocol) {
709 DCHECK(orig_req);
710
711 scoped_refptr<ProtData> prot_data = ProtData::DataFromProtocol(protocol);
712 if (prot_data && prot_data->is_attach_external_tab_request()) {
713 prot_data->Release();
714 return S_OK;
715 }
716
717 return orig_req(protocol);
718 }
719
632 // Patching / Hooking code. 720 // Patching / Hooking code.
633 class FakeProtocol : public CComObjectRootEx<CComSingleThreadModel>, 721 class FakeProtocol : public CComObjectRootEx<CComSingleThreadModel>,
634 public IInternetProtocol { 722 public IInternetProtocol {
635 public: 723 public:
636 BEGIN_COM_MAP(FakeProtocol) 724 BEGIN_COM_MAP(FakeProtocol)
637 COM_INTERFACE_ENTRY(IInternetProtocol) 725 COM_INTERFACE_ENTRY(IInternetProtocol)
638 COM_INTERFACE_ENTRY(IInternetProtocolRoot) 726 COM_INTERFACE_ENTRY(IInternetProtocolRoot)
639 END_COM_MAP() 727 END_COM_MAP()
640 728
641 STDMETHOD(Start)(LPCWSTR url, IInternetProtocolSink *protocol_sink, 729 STDMETHOD(Start)(LPCWSTR url, IInternetProtocolSink *protocol_sink,
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
731 // Explicit release, otherwise ~CComObjectStackEx will complain about 819 // Explicit release, otherwise ~CComObjectStackEx will complain about
732 // outstanding reference to us, because it runs before ~FakeProtocol 820 // outstanding reference to us, because it runs before ~FakeProtocol
733 prot.transaction_.Release(); 821 prot.transaction_.Release();
734 } 822 }
735 } 823 }
736 824
737 void TransactionHooks::RevertHooks() { 825 void TransactionHooks::RevertHooks() {
738 vtable_patch::UnpatchInterfaceMethods(CTransaction_PatchInfo); 826 vtable_patch::UnpatchInterfaceMethods(CTransaction_PatchInfo);
739 vtable_patch::UnpatchInterfaceMethods(CTransaction2_PatchInfo); 827 vtable_patch::UnpatchInterfaceMethods(CTransaction2_PatchInfo);
740 } 828 }
OLDNEW
« no previous file with comments | « chrome_frame/protocol_sink_wrap.h ('k') | chrome_frame/test/util_unittests.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698