| OLD | NEW |
| 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 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 "chrome_frame/test/chrome_frame_test_utils.h" | 5 #include "chrome_frame/test/chrome_frame_test_utils.h" |
| 6 | 6 |
| 7 #include <atlbase.h> | 7 #include <atlbase.h> |
| 8 #include <atlwin.h> | 8 #include <atlwin.h> |
| 9 #include <iepmapi.h> | 9 #include <iepmapi.h> |
| 10 #include <sddl.h> | 10 #include <sddl.h> |
| 11 | 11 |
| 12 #include "base/message_loop.h" | 12 #include "base/message_loop.h" |
| 13 #include "base/registry.h" // to find IE and firefox | 13 #include "base/registry.h" // to find IE and firefox |
| 14 #include "base/scoped_handle.h" | 14 #include "base/scoped_handle.h" |
| 15 #include "base/scoped_comptr_win.h" | 15 #include "base/scoped_comptr_win.h" |
| 16 #include "base/string_util.h" | 16 #include "base/string_util.h" |
| 17 #include "base/win_util.h" | 17 #include "base/win_util.h" |
| 18 #include "chrome/common/chrome_switches.h" | 18 #include "chrome/common/chrome_switches.h" |
| 19 #include "chrome_frame/utils.h" |
| 19 #include "testing/gtest/include/gtest/gtest.h" | 20 #include "testing/gtest/include/gtest/gtest.h" |
| 20 | 21 |
| 21 namespace chrome_frame_test { | 22 namespace chrome_frame_test { |
| 22 | 23 |
| 23 const wchar_t kIEImageName[] = L"iexplore.exe"; | 24 const wchar_t kIEImageName[] = L"iexplore.exe"; |
| 24 const wchar_t kIEBrokerImageName[] = L"ieuser.exe"; | 25 const wchar_t kIEBrokerImageName[] = L"ieuser.exe"; |
| 25 const wchar_t kFirefoxImageName[] = L"firefox.exe"; | 26 const wchar_t kFirefoxImageName[] = L"firefox.exe"; |
| 26 const wchar_t kOperaImageName[] = L"opera.exe"; | 27 const wchar_t kOperaImageName[] = L"opera.exe"; |
| 27 const wchar_t kSafariImageName[] = L"safari.exe"; | 28 const wchar_t kSafariImageName[] = L"safari.exe"; |
| 28 const wchar_t kChromeImageName[] = L"chrome.exe"; | 29 const wchar_t kChromeImageName[] = L"chrome.exe"; |
| (...skipping 587 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 616 ::GetLastError() != ERROR_NO_TOKEN) { | 617 ::GetLastError() != ERROR_NO_TOKEN) { |
| 617 return true; | 618 return true; |
| 618 } | 619 } |
| 619 | 620 |
| 620 if (token) | 621 if (token) |
| 621 ::CloseHandle(token); | 622 ::CloseHandle(token); |
| 622 | 623 |
| 623 return false; | 624 return false; |
| 624 } | 625 } |
| 625 | 626 |
| 627 HRESULT LaunchIEAsComServer(IWebBrowser2** web_browser) { |
| 628 if (!web_browser) |
| 629 return E_INVALIDARG; |
| 630 |
| 631 HRESULT hr = S_OK; |
| 632 DWORD cocreate_flags = CLSCTX_LOCAL_SERVER; |
| 633 chrome_frame_test::LowIntegrityToken token; |
| 634 // Vista has a bug which manifests itself when a medium integrity process |
| 635 // launches a COM server like IE which runs in protected mode due to UAC. |
| 636 // This causes the IWebBrowser2 interface which is returned to be useless, |
| 637 // i.e it does not receive any events, etc. Our workaround for this is |
| 638 // to impersonate a low integrity token and then launch IE. |
| 639 if (win_util::GetWinVersion() == win_util::WINVERSION_VISTA) { |
| 640 // Create medium integrity browser that will launch IE broker. |
| 641 ScopedComPtr<IWebBrowser2> medium_integrity_browser; |
| 642 hr = medium_integrity_browser.CreateInstance(CLSID_InternetExplorer, NULL, |
| 643 CLSCTX_LOCAL_SERVER); |
| 644 if (FAILED(hr)) |
| 645 return hr; |
| 646 medium_integrity_browser->Quit(); |
| 647 // Broker remains alive. |
| 648 if (!token.Impersonate()) { |
| 649 hr = HRESULT_FROM_WIN32(GetLastError()); |
| 650 return hr; |
| 651 } |
| 652 |
| 653 cocreate_flags |= CLSCTX_ENABLE_CLOAKING; |
| 654 } |
| 655 |
| 656 hr = ::CoCreateInstance(CLSID_InternetExplorer, NULL, |
| 657 cocreate_flags, IID_IWebBrowser2, |
| 658 reinterpret_cast<void**>(web_browser)); |
| 659 // ~LowIntegrityToken() will switch integrity back to medium. |
| 660 return hr; |
| 661 } |
| 662 |
| 663 _ATL_FUNC_INFO WebBrowserEventSink::kNavigateErrorInfo = { |
| 664 CC_STDCALL, VT_EMPTY, 5, { |
| 665 VT_DISPATCH, |
| 666 VT_VARIANT | VT_BYREF, |
| 667 VT_VARIANT | VT_BYREF, |
| 668 VT_VARIANT | VT_BYREF, |
| 669 VT_BOOL | VT_BYREF, |
| 670 } |
| 671 }; |
| 672 |
| 673 _ATL_FUNC_INFO WebBrowserEventSink::kNavigateComplete2Info = { |
| 674 CC_STDCALL, VT_EMPTY, 2, { |
| 675 VT_DISPATCH, |
| 676 VT_VARIANT | VT_BYREF |
| 677 } |
| 678 }; |
| 679 |
| 680 _ATL_FUNC_INFO WebBrowserEventSink::kBeforeNavigate2Info = { |
| 681 CC_STDCALL, VT_EMPTY, 7, { |
| 682 VT_DISPATCH, |
| 683 VT_VARIANT | VT_BYREF, |
| 684 VT_VARIANT | VT_BYREF, |
| 685 VT_VARIANT | VT_BYREF, |
| 686 VT_VARIANT | VT_BYREF, |
| 687 VT_VARIANT | VT_BYREF, |
| 688 VT_BOOL | VT_BYREF |
| 689 } |
| 690 }; |
| 691 |
| 692 _ATL_FUNC_INFO WebBrowserEventSink::kNewWindow3Info = { |
| 693 CC_STDCALL, VT_EMPTY, 5, { |
| 694 VT_DISPATCH | VT_BYREF, |
| 695 VT_BOOL | VT_BYREF, |
| 696 VT_UINT, |
| 697 VT_BSTR, |
| 698 VT_BSTR |
| 699 } |
| 700 }; |
| 701 |
| 702 _ATL_FUNC_INFO WebBrowserEventSink::kVoidMethodInfo = { |
| 703 CC_STDCALL, VT_EMPTY, 0, {NULL}}; |
| 704 |
| 705 _ATL_FUNC_INFO WebBrowserEventSink::kDocumentCompleteInfo = { |
| 706 CC_STDCALL, VT_EMPTY, 2, { |
| 707 VT_DISPATCH, |
| 708 VT_VARIANT | VT_BYREF |
| 709 } |
| 710 }; |
| 711 |
| 712 // WebBrowserEventSink member defines |
| 713 void WebBrowserEventSink::Uninitialize() { |
| 714 DisconnectFromChromeFrame(); |
| 715 if (web_browser2_.get()) { |
| 716 DispEventUnadvise(web_browser2_); |
| 717 web_browser2_->Quit(); |
| 718 web_browser2_.Release(); |
| 719 } |
| 720 } |
| 721 |
| 722 STDMETHODIMP WebBrowserEventSink::OnBeforeNavigate2Internal( |
| 723 IDispatch* dispatch, VARIANT* url, VARIANT* flags, |
| 724 VARIANT* target_frame_name, VARIANT* post_data, VARIANT* headers, |
| 725 VARIANT_BOOL* cancel) { |
| 726 DLOG(INFO) << __FUNCTION__; |
| 727 // Reset any existing reference to chrome frame since this is a new |
| 728 // navigation. |
| 729 chrome_frame_ = NULL; |
| 730 return OnBeforeNavigate2(dispatch, url, flags, target_frame_name, |
| 731 post_data, headers, cancel); |
| 732 } |
| 733 |
| 734 STDMETHODIMP_(void) WebBrowserEventSink::OnNavigateComplete2Internal( |
| 735 IDispatch* dispatch, VARIANT* url) { |
| 736 DLOG(INFO) << __FUNCTION__; |
| 737 ConnectToChromeFrame(); |
| 738 OnNavigateComplete2(dispatch, url); |
| 739 } |
| 740 |
| 741 STDMETHODIMP_(void) WebBrowserEventSink::OnDocumentCompleteInternal( |
| 742 IDispatch* dispatch, VARIANT* url) { |
| 743 DLOG(INFO) << __FUNCTION__; |
| 744 OnDocumentComplete(dispatch, url); |
| 745 } |
| 746 |
| 747 HRESULT WebBrowserEventSink::OnLoadInternal(const VARIANT* param) { |
| 748 DLOG(INFO) << __FUNCTION__ << " " << param->bstrVal; |
| 749 OnLoad(param->bstrVal); |
| 750 return S_OK; |
| 751 } |
| 752 |
| 753 HRESULT WebBrowserEventSink::OnLoadErrorInternal(const VARIANT* param) { |
| 754 DLOG(INFO) << __FUNCTION__ << " " << param->bstrVal; |
| 755 OnLoadError(param->bstrVal); |
| 756 return S_OK; |
| 757 } |
| 758 |
| 759 HRESULT WebBrowserEventSink::OnMessageInternal(const VARIANT* param) { |
| 760 DLOG(INFO) << __FUNCTION__ << " " << param->bstrVal; |
| 761 OnMessage(param->bstrVal); |
| 762 return S_OK; |
| 763 } |
| 764 |
| 765 HRESULT WebBrowserEventSink::LaunchIEAndNavigate( |
| 766 const std::wstring& navigate_url) { |
| 767 HRESULT hr = LaunchIEAsComServer(web_browser2_.Receive()); |
| 768 EXPECT_EQ(S_OK, hr); |
| 769 if (hr == S_OK) { |
| 770 web_browser2_->put_Visible(VARIANT_TRUE); |
| 771 hr = DispEventAdvise(web_browser2_, &DIID_DWebBrowserEvents2); |
| 772 EXPECT_TRUE(hr == S_OK); |
| 773 hr = Navigate(navigate_url); |
| 774 } |
| 775 return hr; |
| 776 } |
| 777 |
| 778 HRESULT WebBrowserEventSink::Navigate(const std::wstring& navigate_url) { |
| 779 VARIANT empty = ScopedVariant::kEmptyVariant; |
| 780 ScopedVariant url; |
| 781 url.Set(navigate_url.c_str()); |
| 782 |
| 783 HRESULT hr = S_OK; |
| 784 hr = web_browser2_->Navigate2(url.AsInput(), &empty, &empty, &empty, &empty); |
| 785 EXPECT_TRUE(hr == S_OK); |
| 786 return hr; |
| 787 } |
| 788 |
| 789 void WebBrowserEventSink::SetFocusToChrome() { |
| 790 chrome_frame_test::SetKeyboardFocusToWindow( |
| 791 GetAttachedChromeRendererWindow(), 1, 1); |
| 792 } |
| 793 |
| 794 void WebBrowserEventSink::SendInputToChrome( |
| 795 const std::string& input_string) { |
| 796 chrome_frame_test::SendInputToWindow( |
| 797 GetAttachedChromeRendererWindow(), input_string); |
| 798 } |
| 799 |
| 800 void WebBrowserEventSink::ConnectToChromeFrame() { |
| 801 DCHECK(web_browser2_); |
| 802 ScopedComPtr<IShellBrowser> shell_browser; |
| 803 DoQueryService(SID_STopLevelBrowser, web_browser2_, |
| 804 shell_browser.Receive()); |
| 805 |
| 806 if (shell_browser) { |
| 807 ScopedComPtr<IShellView> shell_view; |
| 808 shell_browser->QueryActiveShellView(shell_view.Receive()); |
| 809 if (shell_view) { |
| 810 shell_view->GetItemObject(SVGIO_BACKGROUND, __uuidof(IChromeFrame), |
| 811 reinterpret_cast<void**>(chrome_frame_.Receive())); |
| 812 } |
| 813 |
| 814 if (chrome_frame_) { |
| 815 ScopedVariant onmessage(onmessage_.ToDispatch()); |
| 816 ScopedVariant onloaderror(onloaderror_.ToDispatch()); |
| 817 ScopedVariant onload(onload_.ToDispatch()); |
| 818 EXPECT_HRESULT_SUCCEEDED(chrome_frame_->put_onmessage(onmessage)); |
| 819 EXPECT_HRESULT_SUCCEEDED(chrome_frame_->put_onloaderror(onloaderror)); |
| 820 EXPECT_HRESULT_SUCCEEDED(chrome_frame_->put_onload(onload)); |
| 821 } |
| 822 } |
| 823 } |
| 824 |
| 825 void WebBrowserEventSink::DisconnectFromChromeFrame() { |
| 826 if (chrome_frame_) { |
| 827 ScopedVariant dummy(static_cast<IDispatch*>(NULL)); |
| 828 chrome_frame_->put_onmessage(dummy); |
| 829 chrome_frame_->put_onload(dummy); |
| 830 chrome_frame_->put_onloaderror(dummy); |
| 831 chrome_frame_.Release(); |
| 832 } |
| 833 } |
| 834 |
| 835 HWND WebBrowserEventSink::GetAttachedChromeRendererWindow() { |
| 836 DCHECK(chrome_frame_); |
| 837 HWND renderer_window = NULL; |
| 838 ScopedComPtr<IOleWindow> ole_window; |
| 839 ole_window.QueryFrom(chrome_frame_); |
| 840 EXPECT_TRUE(ole_window.get()); |
| 841 |
| 842 if (ole_window) { |
| 843 HWND activex_window = NULL; |
| 844 ole_window->GetWindow(&activex_window); |
| 845 EXPECT_TRUE(IsWindow(activex_window)); |
| 846 |
| 847 // chrome tab window is the first (and the only) child of activex |
| 848 HWND chrome_tab_window = GetWindow(activex_window, GW_CHILD); |
| 849 EXPECT_TRUE(IsWindow(chrome_tab_window)); |
| 850 renderer_window = GetWindow(chrome_tab_window, GW_CHILD); |
| 851 } |
| 852 |
| 853 DCHECK(IsWindow(renderer_window)); |
| 854 return renderer_window; |
| 855 } |
| 856 |
| 857 HRESULT WebBrowserEventSink::SetWebBrowser(IWebBrowser2* web_browser2) { |
| 858 DCHECK(web_browser2_.get() == NULL); |
| 859 web_browser2_ = web_browser2; |
| 860 web_browser2_->put_Visible(VARIANT_TRUE); |
| 861 HRESULT hr = DispEventAdvise(web_browser2_, &DIID_DWebBrowserEvents2); |
| 862 return hr; |
| 863 } |
| 864 |
| 626 } // namespace chrome_frame_test | 865 } // namespace chrome_frame_test |
| OLD | NEW |