15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef CHROME_FRAME_TEST_CHROME_FRAME_TEST_UTILS_H_
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define CHROME_FRAME_TEST_CHROME_FRAME_TEST_UTILS_H_
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <windows.h>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <atlbase.h>
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <atlwin.h>
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string>
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/basictypes.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/cancelable_callback.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/compiler_specific.h"
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/files/file_path.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
209ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "base/message_loop/message_loop.h"
21a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch#include "base/process/process_handle.h"
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/run_loop.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/test/test_reg_util_win.h"
24eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h"
25eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h"
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/win/registry.h"
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/win/scoped_comptr.h"
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome_frame/chrome_tab.h"
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome_frame/test/simulate_input.h"
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome_frame/test_utils.h"
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome_frame/utils.h"
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "gtest/gtest.h"
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Needed for CreateFunctor.
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define GMOCK_MUTANT_INCLUDE_LATE_OBJECT_BINDING
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gmock_mutant.h"
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)interface IWebBrowser2;
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace base {
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class FilePath;
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace chrome_frame_test {
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int CloseVisibleWindowsOnAllThreads(HANDLE process);
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)base::ProcessHandle LaunchIE(const std::wstring& url);
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)base::ProcessHandle LaunchChrome(const std::wstring& url,
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                 const base::FilePath& user_data_dir);
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Attempts to close all open IE windows.
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The return value is the number of windows closed.
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// @note: this function requires COM to be initialized on the calling thread.
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Since the caller might be running in either MTA or STA, the function does
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// not perform this initialization itself.
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int CloseAllIEWindows();
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Saves a screen snapshot to the desktop and logs its location.
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool TakeSnapshotAndLog();
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)extern const wchar_t kIEImageName[];
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)extern const wchar_t kIEBrokerImageName[];
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)extern const char kChromeImageName[];
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)extern const wchar_t kChromeLauncher[];
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)extern const base::TimeDelta kChromeFrameLongNavigationTimeout;
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)extern const base::TimeDelta kChromeFrameVeryLongNavigationTimeout;
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Temporarily impersonate the current thread to low integrity for the lifetime
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// of the object. Destructor will automatically revert integrity level.
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class LowIntegrityToken {
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LowIntegrityToken();
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ~LowIntegrityToken();
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BOOL Impersonate();
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BOOL RevertToSelf();
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected:
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static bool IsImpersonated();
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool impersonated_;
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This class implements the COM IMessageFilter interface and is used to detect
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// hung outgoing COM calls which are typically to IE. If IE is hung for any
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// reason the chrome frame tests should not hang indefinitely. This class
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// basically cancels the outgoing call if the WM_TIMER which is set by the
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TimedMsgLoop object is posted to the message queue.
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class HungCOMCallDetector
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : public CComObjectRootEx<CComMultiThreadModel>,
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      public IMessageFilter,
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      public CWindowImpl<HungCOMCallDetector> {
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HungCOMCallDetector()
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : is_hung_(false) {
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ~HungCOMCallDetector() {
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TearDown();
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BEGIN_MSG_MAP(HungCOMCallDetector)
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MESSAGE_HANDLER(WM_TIMER, OnTimer)
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  END_MSG_MAP()
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BEGIN_COM_MAP(HungCOMCallDetector)
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    COM_INTERFACE_ENTRY(IMessageFilter)
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  END_COM_MAP()
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static CComObject<HungCOMCallDetector>* Setup(int timeout_seconds) {
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CComObject<HungCOMCallDetector>* this_instance  = NULL;
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CComObject<HungCOMCallDetector>::CreateInstance(&this_instance);
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(this_instance != NULL);
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_refptr<HungCOMCallDetector> ref_instance = this_instance;
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    HRESULT hr = ref_instance->Initialize(timeout_seconds);
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (FAILED(hr)) {
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(ERROR) << "Failed to Initialize Hung COM call detector. Error:"
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 << hr;
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return NULL;
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return this_instance;
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void TearDown() {
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (prev_filter_) {
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::win::ScopedComPtr<IMessageFilter> prev_filter;
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CoRegisterMessageFilter(prev_filter_.get(), prev_filter.Receive());
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DCHECK(prev_filter.IsSameObject(this));
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      prev_filter_.Release();
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (IsWindow()) {
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DestroyWindow();
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      m_hWnd = NULL;
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  STDMETHOD_(DWORD, HandleInComingCall)(DWORD call_type,
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        HTASK caller,
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        DWORD tick_count,
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        LPINTERFACEINFO interface_info) {
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SERVERCALL_ISHANDLED;
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  STDMETHOD_(DWORD, RetryRejectedCall)(HTASK callee,
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       DWORD tick_count,
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       DWORD reject_type) {
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return -1;
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  STDMETHOD_(DWORD, MessagePending)(HTASK callee,
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    DWORD tick_count,
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    DWORD pending_type) {
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MSG msg = {0};
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (is_hung_) {
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return PENDINGMSG_CANCELCALL;
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return PENDINGMSG_WAITDEFPROCESS;
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool is_hung() const {
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return is_hung_;
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LRESULT OnTimer(UINT msg, WPARAM wp, LPARAM lp, BOOL& handled) {  // NOLINT
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    is_hung_ = true;
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return 1;
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HRESULT Initialize(int timeout_seconds) {
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Create a window for the purpose of setting a windows timer for
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // detecting whether any outgoing COM call issued in this context
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // hangs.
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We then register a COM message filter which basically looks for the
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // timer posted to this window and cancels the outgoing call.
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Create(HWND_MESSAGE);
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!IsWindow()) {
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(ERROR) << "Failed to create window. Error:" << GetLastError();
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return E_FAIL;
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    HRESULT hr = CoRegisterMessageFilter(this, prev_filter_.Receive());
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (FAILED(hr)) {
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(ERROR) << "Failed to register message filter. Error:" << hr;
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return hr;
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    static const int kHungDetectTimerId = 0x0000baba;
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SetTimer(kHungDetectTimerId, 1000 * (timeout_seconds + 40), NULL);
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return S_OK;
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // used to detect if outgoing COM calls hung.
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool is_hung_;
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::win::ScopedComPtr<IMessageFilter> prev_filter_;
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// MessageLoopForUI wrapper that runs only for a limited time.
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// We need a UI message loop in the main thread.
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class TimedMsgLoop {
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TimedMsgLoop() : snapshot_on_timeout_(false), quit_loop_invoked_(false) {
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void set_snapshot_on_timeout(bool value) {
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    snapshot_on_timeout_ = value;
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void RunFor(base::TimeDelta duration) {
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    quit_loop_invoked_ = false;
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (snapshot_on_timeout_)
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      timeout_closure_.Reset(base::Bind(&TimedMsgLoop::SnapshotAndQuit));
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else
214868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      timeout_closure_.Reset(base::MessageLoop::QuitClosure());
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    loop_.PostDelayedTask(FROM_HERE, timeout_closure_.callback(), duration);
216868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    loop_.base::MessageLoop::Run();
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    timeout_closure_.Cancel();
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void PostTask(const tracked_objects::Location& from_here,
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                const base::Closure& task) {
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    loop_.PostTask(from_here, task);
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void PostDelayedTask(const tracked_objects::Location& from_here,
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       const base::Closure& task, base::TimeDelta delay) {
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    loop_.PostDelayedTask(from_here, task, delay);
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void Quit() {
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Quit after no delay.
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    QuitAfter(base::TimeDelta());
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void QuitAfter(base::TimeDelta delay) {
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    timeout_closure_.Cancel();
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    quit_loop_invoked_ = true;
238868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    loop_.PostDelayedTask(FROM_HERE, base::MessageLoop::QuitClosure(), delay);
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool WasTimedOut() const {
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return !quit_loop_invoked_;
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void RunUntilIdle() {
2462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    loop_.RunUntilIdle();
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static void SnapshotAndQuit() {
2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TakeSnapshotAndLog();
252868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    base::MessageLoop::current()->Quit();
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
255868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  base::MessageLoopForUI loop_;
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::CancelableClosure timeout_closure_;
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool snapshot_on_timeout_;
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool quit_loop_invoked_;
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Saves typing. It's somewhat hard to create a wrapper around
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// testing::InvokeWithoutArgs since it returns a
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// non-public (testing::internal) type.
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define QUIT_LOOP(loop) testing::InvokeWithoutArgs(\
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  testing::CreateFunctor(&loop, &chrome_frame_test::TimedMsgLoop::Quit))
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define QUIT_LOOP_SOON(loop, delay) testing::InvokeWithoutArgs(\
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  testing::CreateFunctor(&loop, &chrome_frame_test::TimedMsgLoop::QuitAfter, \
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         delay))
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Launches IE as a COM server and returns the corresponding IWebBrowser2
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// interface pointer.
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns S_OK on success.
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HRESULT LaunchIEAsComServer(IWebBrowser2** web_browser);
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns the path of the exe passed in.
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::wstring GetExecutableAppPath(const std::wstring& file);
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns the profile path to be used for IE. This varies as per version.
2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)base::FilePath GetProfilePathForIE();
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns the version of the exe passed in.
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::wstring GetExeVersion(const std::wstring& exe_path);
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns the version of Internet Explorer on the machine.
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)IEVersion GetInstalledIEVersion();
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns the folder for CF test data.
2892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)base::FilePath GetTestDataFolder();
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns the folder for Selenium core.
2922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)base::FilePath GetSeleniumTestFolder();
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns the path portion of the url.
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::wstring GetPathFromUrl(const std::wstring& url);
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns the path and query portion of the url.
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::wstring GetPathAndQueryFromUrl(const std::wstring& url);
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Adds the CF meta tag to the html page. Returns true if successful.
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool AddCFMetaTag(std::string* html_data);
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Get text data from the clipboard.
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::wstring GetClipboardText();
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3067dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch// Destroys the clipboard for the current thread. This function must be called
3077dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch// if GetClipboardText() or SetClipboardText() have been invoked.
3087dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid DestroyClipboard();
3097dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Puts the given text data on the clipboard. All previous items on the
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// clipboard are removed.
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SetClipboardText(const std::wstring& text);
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A convenience class to close all open IE windows at the end
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// of a scope.  It's more convenient to do it this way than to
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// explicitly call chrome_frame_test::CloseAllIEWindows at the
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// end of a test since part of the test's cleanup code may be
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// in object destructors that would run after CloseAllIEWindows
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// would get called.
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Ideally all IE windows should be closed when this happens so
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// if the test ran normally, we should not have any windows to
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// close at this point.
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class CloseIeAtEndOfScope {
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CloseIeAtEndOfScope() {}
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ~CloseIeAtEndOfScope();
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Starts the Chrome crash service which enables us to gather crash dumps
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// during test runs.
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)base::ProcessHandle StartCrashService();
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Used in tests where we reference the registry and don't want to run into
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// problems where existing registry settings might conflict with the
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// expectations of the test.
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ScopedVirtualizeHklmAndHkcu {
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ScopedVirtualizeHklmAndHkcu();
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ~ScopedVirtualizeHklmAndHkcu();
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected:
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  registry_util::RegistryOverrideManager override_manager_;
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Attempts to kill all the processes on the current machine that were launched
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// from the given executable name, ending them with the given exit code.  If
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// filter is non-null, then only processes selected by the filter are killed.
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns true if all processes were able to be killed off, false if at least
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// one couldn't be killed.
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// NOTE: This function is based on the base\process_util.h helper function
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// KillProcesses. Takes in the wait flag as a parameter.
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool KillProcesses(const std::wstring& executable_name, int exit_code,
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   bool wait);
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns the type of test bed, PER_USER or SYSTEM_LEVEL.
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ScopedChromeFrameRegistrar::RegistrationType GetTestBedType();
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Clears IE8 session restore history.
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ClearIESessionHistory();
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns a local IPv4 address for the current machine. The address
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// corresponding to a NIC is preferred over the loopback address.
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string GetLocalIPv4Address();
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace chrome_frame_test
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(tommi): This is a temporary workaround while we're getting our
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Singleton story straight.  Ideally each test should clear up any singletons
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// it might have created, but test cases do not implicitly have their own
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// AtExitManager, so we have this workaround method for tests that depend on
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// "fresh" singletons.  The implementation is in chrome_frame_unittest_main.cc.
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DeleteAllSingletons();
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // CHROME_FRAME_TEST_CHROME_FRAME_TEST_UTILS_H_
375