| Index: chrome_frame/test/perf/chrome_frame_perftest.cc
 | 
| ===================================================================
 | 
| --- chrome_frame/test/perf/chrome_frame_perftest.cc	(revision 0)
 | 
| +++ chrome_frame/test/perf/chrome_frame_perftest.cc	(revision 0)
 | 
| @@ -0,0 +1,1137 @@
 | 
| +// Copyright (c) 2006-2009 The Chromium Authors. All rights reserved.
 | 
| +// Use of this source code is governed by a BSD-style license that can be
 | 
| +// found in the LICENSE file.
 | 
| +#include "chrome_frame/test/perf/chrome_frame_perftest.h"
 | 
| +
 | 
| +#include <atlwin.h>
 | 
| +#include <atlhost.h>
 | 
| +#include <map>
 | 
| +#include <vector>
 | 
| +#include <string>
 | 
| +
 | 
| +#include "chrome_tab.h"  // Generated from chrome_tab.idl.
 | 
| +
 | 
| +#include "base/file_util.h"
 | 
| +#include "base/registry.h"
 | 
| +#include "base/scoped_ptr.h"
 | 
| +#include "base/scoped_bstr_win.h"
 | 
| +#include "base/scoped_comptr_win.h"
 | 
| +#include "base/string_util.h"
 | 
| +#include "base/time.h"
 | 
| +#include "chrome/common/chrome_constants.h"
 | 
| +#include "chrome/common/chrome_paths.h"
 | 
| +#include "chrome/test/chrome_process_util.h"
 | 
| +#include "chrome/test/perf/mem_usage.h"
 | 
| +#include "chrome/test/ui/ui_test.h"
 | 
| +
 | 
| +#include "chrome_frame/test_utils.h"
 | 
| +#include "chrome_frame/utils.h"
 | 
| +
 | 
| +const wchar_t kSilverlightControlKey[] =
 | 
| +    L"CLSID\\{DFEAF541-F3E1-4c24-ACAC-99C30715084A}\\InprocServer32";
 | 
| +
 | 
| +const wchar_t kFlashControlKey[] =
 | 
| +    L"CLSID\\{D27CDB6E-AE6D-11cf-96B8-444553540000}\\InprocServer32";
 | 
| +
 | 
| +using base::TimeDelta;
 | 
| +using base::TimeTicks;
 | 
| +
 | 
| +// Callback description for onload, onloaderror, onmessage
 | 
| +static _ATL_FUNC_INFO g_single_param = {CC_STDCALL, VT_EMPTY, 1, {VT_VARIANT}};
 | 
| +// Simple class that forwards the callbacks.
 | 
| +template <typename T>
 | 
| +class DispCallback
 | 
| +    : public IDispEventSimpleImpl<1, DispCallback<T>, &IID_IDispatch> {
 | 
| + public:
 | 
| +  typedef HRESULT (T::*Method)(VARIANT* param);
 | 
| +
 | 
| +  DispCallback(T* owner, Method method) : owner_(owner), method_(method) {
 | 
| +  }
 | 
| +
 | 
| +  BEGIN_SINK_MAP(DispCallback)
 | 
| +    SINK_ENTRY_INFO(1, IID_IDispatch, DISPID_VALUE, OnCallback, &g_single_param)
 | 
| +  END_SINK_MAP()
 | 
| +
 | 
| +  virtual ULONG STDMETHODCALLTYPE AddRef() {
 | 
| +    return owner_->AddRef();
 | 
| +  }
 | 
| +  virtual ULONG STDMETHODCALLTYPE Release() {
 | 
| +    return owner_->Release();
 | 
| +  }
 | 
| +
 | 
| +  STDMETHOD(OnCallback)(VARIANT param) {
 | 
| +    return (owner_->*method_)(¶m);
 | 
| +  }
 | 
| +
 | 
| +  IDispatch* ToDispatch() {
 | 
| +    return reinterpret_cast<IDispatch*>(this);
 | 
| +  }
 | 
| +
 | 
| +  T* owner_;
 | 
| +  Method method_;
 | 
| +};
 | 
| +
 | 
| +// This class implements an ActiveX container which hosts the ChromeFrame
 | 
| +// ActiveX control. It provides hooks which can be implemented by derived
 | 
| +// classes for implementing performance measurement, etc.
 | 
| +class ChromeFrameActiveXContainer
 | 
| +    : public CWindowImpl<ChromeFrameActiveXContainer, CWindow, CWinTraits <
 | 
| +          WS_OVERLAPPEDWINDOW | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
 | 
| +          WS_EX_APPWINDOW | WS_EX_WINDOWEDGE> >,
 | 
| +      public CComObjectRootEx<CComSingleThreadModel>,
 | 
| +      public IPropertyNotifySink {
 | 
| + public:
 | 
| +  ~ChromeFrameActiveXContainer() {
 | 
| +    if (m_hWnd)
 | 
| +      DestroyWindow();
 | 
| +  }
 | 
| +
 | 
| +  DECLARE_WND_CLASS_EX(L"ChromeFrameActiveX_container", 0, 0)
 | 
| +
 | 
| +  BEGIN_COM_MAP(ChromeFrameActiveXContainer)
 | 
| +    COM_INTERFACE_ENTRY(IPropertyNotifySink)
 | 
| +  END_COM_MAP()
 | 
| +
 | 
| +  BEGIN_MSG_MAP(ChromeFrameActiveXContainer)
 | 
| +    MESSAGE_HANDLER(WM_CREATE, OnCreate)
 | 
| +    MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
 | 
| +  END_MSG_MAP()
 | 
| +
 | 
| +  HRESULT OnMessageCallback(VARIANT* param) {
 | 
| +    DLOG(INFO) << __FUNCTION__;
 | 
| +    OnMessageCallbackImpl(param);
 | 
| +    return S_OK;
 | 
| +  }
 | 
| +
 | 
| +  HRESULT OnLoadErrorCallback(VARIANT* param) {
 | 
| +    DLOG(INFO) << __FUNCTION__ << " " << param->bstrVal;
 | 
| +    OnLoadErrorCallbackImpl(param);
 | 
| +    return S_OK;
 | 
| +  }
 | 
| +
 | 
| +  HRESULT OnLoadCallback(VARIANT* param) {
 | 
| +    DLOG(INFO) << __FUNCTION__ << " " << param->bstrVal;
 | 
| +    OnLoadCallbackImpl(param);
 | 
| +    return S_OK;
 | 
| +  }
 | 
| +
 | 
| +  ChromeFrameActiveXContainer() :
 | 
| +      prop_notify_cookie_(0),
 | 
| +      onmsg_(this, &ChromeFrameActiveXContainer::OnMessageCallback),
 | 
| +      onloaderror_(this, &ChromeFrameActiveXContainer::OnLoadErrorCallback),
 | 
| +      onload_(this, &ChromeFrameActiveXContainer::OnLoadCallback) {
 | 
| +  }
 | 
| +
 | 
| +  LRESULT OnCreate(UINT , WPARAM , LPARAM , BOOL& ) {
 | 
| +    chromeview_.Attach(m_hWnd);
 | 
| +    return 0;
 | 
| +  }
 | 
| +
 | 
| +  // This will be called twice.
 | 
| +  // Once from CAxHostWindow::OnDestroy (through DefWindowProc)
 | 
| +  // and once more from the ATL since CAxHostWindow::OnDestroy claims the
 | 
| +  // message is not handled.
 | 
| +  LRESULT OnDestroy(UINT, WPARAM, LPARAM, BOOL& handled) {  // NOLINT
 | 
| +    if (prop_notify_cookie_) {
 | 
| +      AtlUnadvise(tab_, IID_IPropertyNotifySink, prop_notify_cookie_);
 | 
| +      prop_notify_cookie_ = 0;
 | 
| +    }
 | 
| +
 | 
| +    tab_.Release();
 | 
| +    return 0;
 | 
| +  }
 | 
| +
 | 
| +  virtual void OnFinalMessage(HWND /*hWnd*/) {
 | 
| +    ::PostQuitMessage(6);
 | 
| +  }
 | 
| +
 | 
| +  static const wchar_t* GetWndCaption() {
 | 
| +    return L"ChromeFrame Container";
 | 
| +  }
 | 
| +
 | 
| +  // IPropertyNotifySink
 | 
| +  STDMETHOD(OnRequestEdit)(DISPID disp_id) {
 | 
| +    OnRequestEditImpl(disp_id);
 | 
| +    return S_OK;
 | 
| +  }
 | 
| +
 | 
| +  STDMETHOD(OnChanged)(DISPID disp_id) {
 | 
| +    if (disp_id != DISPID_READYSTATE)
 | 
| +      return S_OK;
 | 
| +
 | 
| +    long ready_state;
 | 
| +    HRESULT hr = tab_->get_readyState(&ready_state);
 | 
| +    DCHECK(hr == S_OK);
 | 
| +
 | 
| +    OnReadyStateChanged(ready_state);
 | 
| +
 | 
| +    if (ready_state == READYSTATE_COMPLETE) {
 | 
| +      if(!starting_url_.empty()) {
 | 
| +        Navigate(starting_url_.c_str());
 | 
| +      } else {
 | 
| +        PostMessage(WM_CLOSE);
 | 
| +      }
 | 
| +    } else if (ready_state == READYSTATE_UNINITIALIZED) {
 | 
| +      DLOG(ERROR) << __FUNCTION__ << " Chrome launch failed.";
 | 
| +    }
 | 
| +
 | 
| +    return S_OK;
 | 
| +  }
 | 
| +
 | 
| +  void CreateChromeFrameWindow(const std::string& starting_url) {
 | 
| +    starting_url_ = starting_url;
 | 
| +    RECT rc = { 0, 0, 800, 600 };
 | 
| +    Create(NULL, rc);
 | 
| +    DCHECK(m_hWnd);
 | 
| +    ShowWindow(SW_SHOWDEFAULT);
 | 
| +  }
 | 
| +
 | 
| +  void CreateControl(bool setup_event_sinks) {
 | 
| +    HRESULT hr = chromeview_.CreateControl(L"ChromeTab.ChromeFrame");
 | 
| +    EXPECT_HRESULT_SUCCEEDED(hr);
 | 
| +    hr = chromeview_.QueryControl(tab_.Receive());
 | 
| +    EXPECT_HRESULT_SUCCEEDED(hr);
 | 
| +
 | 
| +    if (setup_event_sinks)
 | 
| +      SetupEventSinks();
 | 
| +  }
 | 
| +
 | 
| +  void Navigate(const char* url) {
 | 
| +    BeforeNavigateImpl(url);
 | 
| +
 | 
| +    HRESULT hr = tab_->put_src(ScopedBstr(UTF8ToWide(url).c_str()));
 | 
| +    DCHECK(hr == S_OK) << "Chrome frame NavigateToURL(" << url
 | 
| +                       << StringPrintf(L") failed 0x%08X", hr);
 | 
| +  }
 | 
| +
 | 
| +  void SetupEventSinks() {
 | 
| +    HRESULT hr = AtlAdvise(tab_, this, IID_IPropertyNotifySink,
 | 
| +                           &prop_notify_cookie_);
 | 
| +    DCHECK(hr == S_OK) << "AtlAdvice for IPropertyNotifySink failed " << hr;
 | 
| +
 | 
| +    CComVariant onmessage(onmsg_.ToDispatch());
 | 
| +    CComVariant onloaderror(onloaderror_.ToDispatch());
 | 
| +    CComVariant onload(onload_.ToDispatch());
 | 
| +    EXPECT_HRESULT_SUCCEEDED(tab_->put_onmessage(onmessage));
 | 
| +    EXPECT_HRESULT_SUCCEEDED(tab_->put_onloaderror(onloaderror));
 | 
| +    EXPECT_HRESULT_SUCCEEDED(tab_->put_onload(onload));
 | 
| +  }
 | 
| +
 | 
| + protected:
 | 
| +  // These functions are implemented by derived classes for special behavior
 | 
| +  // like performance measurement, etc.
 | 
| +  virtual void OnReadyStateChanged(long ready_state) {}
 | 
| +  virtual void OnRequestEditImpl(DISPID disp_id) {}
 | 
| +
 | 
| +  virtual void OnMessageCallbackImpl(VARIANT* param) {}
 | 
| +
 | 
| +  virtual void OnLoadCallbackImpl(VARIANT* param) {
 | 
| +    PostMessage(WM_CLOSE);
 | 
| +  }
 | 
| +
 | 
| +  virtual void OnLoadErrorCallbackImpl(VARIANT* param) {
 | 
| +    PostMessage(WM_CLOSE);
 | 
| +  }
 | 
| +  virtual void BeforeNavigateImpl(const char* url) {}
 | 
| +
 | 
| +  CAxWindow chromeview_;
 | 
| +  ScopedComPtr<IChromeFrame> tab_;
 | 
| +  DWORD prop_notify_cookie_;
 | 
| +  DispCallback<ChromeFrameActiveXContainer> onmsg_;
 | 
| +  DispCallback<ChromeFrameActiveXContainer> onloaderror_;
 | 
| +  DispCallback<ChromeFrameActiveXContainer> onload_;
 | 
| +  std::string starting_url_;
 | 
| +};
 | 
| +
 | 
| +// This class overrides the hooks provided by the ChromeFrameActiveXContainer
 | 
| +// class and measures performance at various stages, like initialzation of
 | 
| +// the Chrome frame widget, navigation, etc.
 | 
| +class ChromeFrameActiveXContainerPerf : public ChromeFrameActiveXContainer {
 | 
| + public:
 | 
| +  ChromeFrameActiveXContainerPerf() {}
 | 
| +
 | 
| +  void CreateControl(bool setup_event_sinks) {
 | 
| +    perf_initialize_.reset(new PerfTimeLogger("Fully initialized"));
 | 
| +    PerfTimeLogger perf_create("Create Control");
 | 
| +
 | 
| +    HRESULT hr = chromeview_.CreateControl(L"ChromeTab.ChromeFrame");
 | 
| +    EXPECT_HRESULT_SUCCEEDED(hr);
 | 
| +    hr = chromeview_.QueryControl(tab_.Receive());
 | 
| +    EXPECT_HRESULT_SUCCEEDED(hr);
 | 
| +
 | 
| +    perf_create.Done();
 | 
| +    if (setup_event_sinks)
 | 
| +      SetupEventSinks();
 | 
| +  }
 | 
| +
 | 
| + protected:
 | 
| +  virtual void OnReadyStateChanged(long ready_state) {
 | 
| +    // READYSTATE_COMPLETE is fired when the automation server is ready.
 | 
| +    if (ready_state == READYSTATE_COMPLETE) {
 | 
| +      perf_initialize_->Done();
 | 
| +    } else if (ready_state == READYSTATE_INTERACTIVE) {
 | 
| +      // Window ready.  Currently we never receive this notification because it
 | 
| +      // is fired before we finish setting up our hosting environment.
 | 
| +      // This is because of how ATL is written.  Moving forward we might
 | 
| +      // have our own hosting classes and then have more control over when we
 | 
| +      // set up the prop notify sink.
 | 
| +    } else {
 | 
| +      DCHECK(ready_state != READYSTATE_UNINITIALIZED) << "failed to initialize";
 | 
| +    }
 | 
| +  }
 | 
| +
 | 
| +  virtual void OnLoadCallbackImpl(VARIANT* param) {
 | 
| +    PostMessage(WM_CLOSE);
 | 
| +    perf_navigate_->Done();
 | 
| +  }
 | 
| +
 | 
| +  virtual void OnLoadErrorCallbackImpl(VARIANT* param) {
 | 
| +    PostMessage(WM_CLOSE);
 | 
| +    perf_navigate_->Done();
 | 
| +  }
 | 
| +
 | 
| +  virtual void BeforeNavigateImpl(const char* url ) {
 | 
| +    std::string test_name = "Navigate ";
 | 
| +    test_name += url;
 | 
| +    perf_navigate_.reset(new PerfTimeLogger(test_name.c_str()));
 | 
| +  }
 | 
| +
 | 
| +  scoped_ptr<PerfTimeLogger> perf_initialize_;
 | 
| +  scoped_ptr<PerfTimeLogger> perf_navigate_;
 | 
| +};
 | 
| +
 | 
| +// This class provides common functionality which can be used for most of the
 | 
| +// ChromeFrame/Tab performance tests.
 | 
| +class ChromeFramePerfTestBase : public UITest {
 | 
| + public:
 | 
| +  ChromeFramePerfTestBase() {}
 | 
| + protected:
 | 
| +  scoped_ptr<ScopedChromeFrameRegistrar> chrome_frame_registrar_;
 | 
| +};
 | 
| +
 | 
| +class ChromeFrameStartupTest : public ChromeFramePerfTestBase {
 | 
| + public:
 | 
| +  ChromeFrameStartupTest() {}
 | 
| +
 | 
| +  virtual void SetUp() {
 | 
| +    ASSERT_TRUE(PathService::Get(chrome::DIR_APP, &dir_app_));
 | 
| +
 | 
| +    chrome_dll_ = dir_app_.Append(FILE_PATH_LITERAL("chrome.dll"));
 | 
| +    chrome_exe_ = dir_app_.Append(
 | 
| +        FilePath::FromWStringHack(chrome::kBrowserProcessExecutableName));
 | 
| +    chrome_frame_dll_ = dir_app_.Append(
 | 
| +        FILE_PATH_LITERAL("servers\\npchrome_tab.dll"));
 | 
| +  }
 | 
| +  virtual void TearDown() {}
 | 
| +
 | 
| +  // TODO(iyengar)
 | 
| +  // This function is similar to the RunStartupTest function used in chrome
 | 
| +  // startup tests. Refactor into a common implementation.
 | 
| +  void RunStartupTest(const char* graph, const char* trace,
 | 
| +                      const char* startup_url, bool test_cold,
 | 
| +                      int total_binaries, const FilePath binaries_to_evict[],
 | 
| +                      bool important, bool ignore_cache_error) {
 | 
| +    const int kNumCycles = 20;
 | 
| +
 | 
| +    startup_url_ = startup_url;
 | 
| +
 | 
| +    TimeDelta timings[kNumCycles];
 | 
| +
 | 
| +    for (int i = 0; i < kNumCycles; ++i) {
 | 
| +      if (test_cold) {
 | 
| +        for (int binary_index = 0; binary_index < total_binaries;
 | 
| +             binary_index++) {
 | 
| +          bool result = EvictFileFromSystemCacheWrapper(
 | 
| +              binaries_to_evict[binary_index]);
 | 
| +          if (!ignore_cache_error) {
 | 
| +            ASSERT_TRUE(result);
 | 
| +          } else if (!result) {
 | 
| +            printf("\nFailed to evict file %ls from cache. Not running test\n",
 | 
| +                   binaries_to_evict[binary_index].value().c_str());
 | 
| +            return;
 | 
| +          }
 | 
| +        }
 | 
| +      }
 | 
| +
 | 
| +      TimeTicks start_time, end_time;
 | 
| +
 | 
| +      RunStartupTestImpl(&start_time, &end_time);
 | 
| +
 | 
| +      timings[i] = end_time - start_time;
 | 
| +
 | 
| +      CoFreeUnusedLibraries();
 | 
| +      ASSERT_TRUE(GetModuleHandle(L"npchrome_tab.dll") == NULL);
 | 
| +
 | 
| +      // TODO(beng): Can't shut down so quickly. Figure out why, and fix. If we
 | 
| +      // do, we crash.
 | 
| +      PlatformThread::Sleep(50);
 | 
| +    }
 | 
| +
 | 
| +    std::string times;
 | 
| +    for (int i = 0; i < kNumCycles; ++i)
 | 
| +      StringAppendF(×, "%.2f,", timings[i].InMillisecondsF());
 | 
| +
 | 
| +    PrintResultList(graph, "", trace, times, "ms", important);
 | 
| +  }
 | 
| +
 | 
| +  FilePath dir_app_;
 | 
| +  FilePath chrome_dll_;
 | 
| +  FilePath chrome_exe_;
 | 
| +  FilePath chrome_frame_dll_;
 | 
| +
 | 
| + protected:
 | 
| +  // Individual startup tests should implement this function.
 | 
| +  virtual void RunStartupTestImpl(TimeTicks* start_time,
 | 
| +                                  TimeTicks* end_time) {}
 | 
| +
 | 
| +  // The host is torn down by this function. It should not be used after
 | 
| +  // this function returns.
 | 
| +  static void ReleaseHostComReferences(CAxWindow& host) {
 | 
| +    CComPtr<IAxWinHostWindow> spWinHost;
 | 
| +    host.QueryHost(&spWinHost);
 | 
| +    ASSERT_TRUE(spWinHost != NULL);
 | 
| +
 | 
| +    // Hack to get the host to release all interfaces and thus ensure that
 | 
| +    // the COM server can be unloaded.
 | 
| +    CAxHostWindow* host_window = static_cast<CAxHostWindow*>(spWinHost.p);
 | 
| +    host_window->ReleaseAll();
 | 
| +    host.DestroyWindow();
 | 
| +  }
 | 
| +
 | 
| +  std::string startup_url_;
 | 
| +};
 | 
| +
 | 
| +class ChromeFrameStartupTestActiveX : public ChromeFrameStartupTest {
 | 
| + public:
 | 
| +  virtual void SetUp() {
 | 
| +    // Register the Chrome Frame DLL in the build directory.
 | 
| +    chrome_frame_registrar_.reset(new ScopedChromeFrameRegistrar);
 | 
| +
 | 
| +    ChromeFrameStartupTest::SetUp();
 | 
| +  }
 | 
| +
 | 
| + protected:
 | 
| +  virtual void RunStartupTestImpl(TimeTicks* start_time,
 | 
| +                                  TimeTicks* end_time) {
 | 
| +    *start_time = TimeTicks::Now();
 | 
| +    SimpleModule module;
 | 
| +    AtlAxWinInit();
 | 
| +    CComObjectStackEx<ChromeFrameActiveXContainer> wnd;
 | 
| +    wnd.CreateChromeFrameWindow(startup_url_);
 | 
| +    wnd.CreateControl(true);
 | 
| +    module.RunMessageLoop();
 | 
| +    *end_time = TimeTicks::Now();
 | 
| +  }
 | 
| +};
 | 
| +
 | 
| +// This class measures the load time of chrome and chrome frame binaries
 | 
| +class ChromeFrameBinariesLoadTest : public ChromeFrameStartupTestActiveX {
 | 
| + protected:
 | 
| +  virtual void RunStartupTestImpl(TimeTicks* start_time,
 | 
| +                                  TimeTicks* end_time) {
 | 
| +    *start_time = TimeTicks::Now();
 | 
| +
 | 
| +    HMODULE chrome_exe = LoadLibrary(chrome_exe_.ToWStringHack().c_str());
 | 
| +    ASSERT_TRUE(chrome_exe != NULL);
 | 
| +
 | 
| +    HMODULE chrome_dll = LoadLibrary(chrome_dll_.ToWStringHack().c_str());
 | 
| +    ASSERT_TRUE(chrome_dll != NULL);
 | 
| +
 | 
| +    HMODULE chrome_tab_dll =
 | 
| +        LoadLibrary(chrome_frame_dll_.ToWStringHack().c_str());
 | 
| +    ASSERT_TRUE(chrome_tab_dll != NULL);
 | 
| +
 | 
| +    *end_time = TimeTicks::Now();
 | 
| +
 | 
| +    FreeLibrary(chrome_exe);
 | 
| +    FreeLibrary(chrome_dll);
 | 
| +    FreeLibrary(chrome_tab_dll);
 | 
| +  }
 | 
| +};
 | 
| +
 | 
| +// This class provides functionality to run the startup performance test for
 | 
| +// the ChromeFrame ActiveX against a reference build. At this point we only run
 | 
| +// this test in warm mode.
 | 
| +class ChromeFrameStartupTestActiveXReference
 | 
| +    : public ChromeFrameStartupTestActiveX {
 | 
| + public:
 | 
| +  // override the browser directory to use the reference build instead.
 | 
| +  virtual void SetUp() {
 | 
| +    // Register the reference build Chrome Frame DLL.
 | 
| +    chrome_frame_registrar_.reset(new ScopedChromeFrameRegistrar);
 | 
| +    chrome_frame_registrar_->RegisterReferenceChromeFrameBuild();
 | 
| +
 | 
| +    ChromeFrameStartupTest::SetUp();
 | 
| +    chrome_frame_dll_ = FilePath::FromWStringHack(
 | 
| +        chrome_frame_registrar_->GetChromeFrameDllPath());
 | 
| +  }
 | 
| +
 | 
| +  virtual void TearDown() {
 | 
| +    // Reregister the Chrome Frame DLL in the build directory.
 | 
| +    chrome_frame_registrar_.reset(NULL);
 | 
| +  }
 | 
| +};
 | 
| +
 | 
| +// This class provides base functionality to measure ChromeFrame memory
 | 
| +// usage.
 | 
| +// TODO(iyengar)
 | 
| +// Some of the functionality in this class like printing the results, etc
 | 
| +// is based on the chrome\test\memory_test.cc. We need to factor out
 | 
| +// the common code.
 | 
| +class ChromeFrameMemoryTest : public ChromeFramePerfTestBase {
 | 
| +
 | 
| +  // Contains information about the memory consumption of a process.
 | 
| +  class ProcessMemoryInfo {
 | 
| +   public:
 | 
| +    // Default constructor
 | 
| +    // Added to enable us to add ProcessMemoryInfo instances to a map.
 | 
| +    ProcessMemoryInfo()
 | 
| +        : process_id_(0),
 | 
| +          peak_virtual_size_(0),
 | 
| +          virtual_size_(0),
 | 
| +          peak_working_set_size_(0),
 | 
| +          working_set_size_(0),
 | 
| +          chrome_browser_process_(false),
 | 
| +          chrome_frame_memory_test_instance_(NULL) {}
 | 
| +
 | 
| +    ProcessMemoryInfo(base::ProcessId process_id, bool chrome_browser_process,
 | 
| +                     ChromeFrameMemoryTest* memory_test_instance)
 | 
| +        : process_id_(process_id),
 | 
| +          peak_virtual_size_(0),
 | 
| +          virtual_size_(0),
 | 
| +          peak_working_set_size_(0),
 | 
| +          working_set_size_(0),
 | 
| +          chrome_browser_process_(chrome_browser_process),
 | 
| +          chrome_frame_memory_test_instance_(memory_test_instance) {}
 | 
| +
 | 
| +    bool GetMemoryConsumptionDetails() {
 | 
| +      return GetMemoryInfo(process_id_,
 | 
| +                           &peak_virtual_size_,
 | 
| +                           &virtual_size_,
 | 
| +                           &peak_working_set_size_,
 | 
| +                           &working_set_size_);
 | 
| +    }
 | 
| +
 | 
| +    void Print(const char* test_name) {
 | 
| +      std::string trace_name(test_name);
 | 
| +
 | 
| +      ASSERT_TRUE(chrome_frame_memory_test_instance_ != NULL);
 | 
| +
 | 
| +      if (chrome_browser_process_) {
 | 
| +         chrome_frame_memory_test_instance_->PrintResult(
 | 
| +             "vm_final_browser", "", trace_name + "_vm_b",
 | 
| +             virtual_size_ / 1024, "KB", false /* not important */);
 | 
| +         chrome_frame_memory_test_instance_->PrintResult(
 | 
| +             "ws_final_browser", "", trace_name + "_ws_b",
 | 
| +             working_set_size_ / 1024, "KB", false /* not important */);
 | 
| +      } else if (process_id_ == GetCurrentProcessId()) {
 | 
| +        chrome_frame_memory_test_instance_->PrintResult(
 | 
| +            "vm_current_process", "", trace_name + "_vm_c",
 | 
| +            virtual_size_ / 1024, "KB", false /* not important */);
 | 
| +        chrome_frame_memory_test_instance_->PrintResult(
 | 
| +            "ws_current_process", "", trace_name + "_ws_c",
 | 
| +            working_set_size_ / 1024, "KB", false /* not important */);
 | 
| +      }
 | 
| +
 | 
| +      printf("\n");
 | 
| +    }
 | 
| +
 | 
| +    int process_id_;
 | 
| +    size_t peak_virtual_size_;
 | 
| +    size_t virtual_size_;
 | 
| +    size_t peak_working_set_size_;
 | 
| +    size_t working_set_size_;
 | 
| +    // Set to true if this is the chrome browser process.
 | 
| +    bool chrome_browser_process_;
 | 
| +
 | 
| +    // A reference to the ChromeFrameMemoryTest instance. Used to print memory
 | 
| +    // consumption information.
 | 
| +    ChromeFrameMemoryTest* chrome_frame_memory_test_instance_;
 | 
| +  };
 | 
| +
 | 
| +  // This map tracks memory usage for a process. It is keyed on the process
 | 
| +  // id.
 | 
| +  typedef std::map<DWORD, ProcessMemoryInfo> ProcessMemoryConsumptionMap;
 | 
| +
 | 
| + public:
 | 
| +  ChromeFrameMemoryTest()
 | 
| +      : current_url_index_(0),
 | 
| +        browser_pid_(0) {}
 | 
| +
 | 
| +  virtual void SetUp() {
 | 
| +    // Register the Chrome Frame DLL in the build directory.
 | 
| +    chrome_frame_registrar_.reset(new ScopedChromeFrameRegistrar);
 | 
| +  }
 | 
| +
 | 
| +  void RunTest(const char* test_name, char* urls[], int total_urls) {
 | 
| +    ASSERT_TRUE(urls != NULL);
 | 
| +    ASSERT_GT(total_urls, 0);
 | 
| +
 | 
| +    // Record the initial CommitCharge.  This is a system-wide measurement,
 | 
| +    // so if other applications are running, they can create variance in this
 | 
| +    // test.
 | 
| +    start_commit_charge_ = GetSystemCommitCharge();
 | 
| +
 | 
| +    for (int i = 0; i < total_urls; i++)
 | 
| +      urls_.push_back(urls[i]);
 | 
| +
 | 
| +    std::string url;
 | 
| +    GetNextUrl(&url);
 | 
| +    ASSERT_TRUE(!url.empty());
 | 
| +
 | 
| +    StartTest(url, test_name);
 | 
| +  }
 | 
| +
 | 
| +  void OnNavigationSuccess(VARIANT* param) {
 | 
| +    ASSERT_TRUE(param != NULL);
 | 
| +    ASSERT_EQ(VT_BSTR, param->vt);
 | 
| +
 | 
| +    DLOG(INFO) << __FUNCTION__ << " " << param->bstrVal;
 | 
| +    InitiateNextNavigation();
 | 
| +  }
 | 
| +
 | 
| +  void OnNavigationFailure(VARIANT* param) {
 | 
| +    ASSERT_TRUE(param != NULL);
 | 
| +    ASSERT_EQ(VT_BSTR, param->vt);
 | 
| +
 | 
| +    DLOG(INFO) << __FUNCTION__ << " " << param->bstrVal;
 | 
| +    InitiateNextNavigation();
 | 
| +  }
 | 
| +
 | 
| + protected:
 | 
| +  bool GetNextUrl(std::string* url) {
 | 
| +    if (current_url_index_ >= urls_.size())
 | 
| +      return false;
 | 
| +
 | 
| +    *url = urls_[current_url_index_++];
 | 
| +    return true;
 | 
| +  }
 | 
| +
 | 
| +  // Returns the path of the current chrome.exe being used by this test.
 | 
| +  // This could return the regular chrome path or that of the reference
 | 
| +  // build.
 | 
| +  std::wstring GetChromeExePath() {
 | 
| +    std::wstring chrome_exe_path =
 | 
| +        chrome_frame_registrar_->GetChromeFrameDllPath();
 | 
| +    EXPECT_FALSE(chrome_exe_path.empty());
 | 
| +
 | 
| +    file_util::UpOneDirectory(&chrome_exe_path);
 | 
| +
 | 
| +    std::wstring chrome_exe_test_path = chrome_exe_path;
 | 
| +    file_util::AppendToPath(&chrome_exe_test_path,
 | 
| +                            chrome::kBrowserProcessExecutableName);
 | 
| +
 | 
| +    if (!file_util::PathExists(chrome_exe_test_path)) {
 | 
| +      file_util::UpOneDirectory(&chrome_exe_path);
 | 
| +
 | 
| +      chrome_exe_test_path = chrome_exe_path;
 | 
| +      file_util::AppendToPath(&chrome_exe_test_path,
 | 
| +                              chrome::kBrowserProcessExecutableName);
 | 
| +    }
 | 
| +
 | 
| +    EXPECT_TRUE(file_util::PathExists(chrome_exe_test_path));
 | 
| +
 | 
| +    return chrome_exe_path;
 | 
| +  }
 | 
| +
 | 
| +  void InitiateNextNavigation() {
 | 
| +    if (browser_pid_ == 0) {
 | 
| +      std::wstring profile_directory;
 | 
| +      if (GetUserProfileBaseDirectory(&profile_directory)) {
 | 
| +        file_util::AppendToPath(&profile_directory,
 | 
| +                                GetHostProcessName(false));
 | 
| +      }
 | 
| +
 | 
| +      user_data_dir_ = FilePath::FromWStringHack(profile_directory);
 | 
| +      browser_pid_ = ChromeBrowserProcessId(user_data_dir_);
 | 
| +    }
 | 
| +
 | 
| +    EXPECT_TRUE(static_cast<int>(browser_pid_) > 0);
 | 
| +
 | 
| +    // Get the memory consumption information for the child processes
 | 
| +    // of the chrome browser.
 | 
| +    ChromeProcessList child_processes = GetBrowserChildren();
 | 
| +    ChromeProcessList::iterator index;
 | 
| +    for (index = child_processes.begin(); index != child_processes.end();
 | 
| +         ++index) {
 | 
| +      AccountProcessMemoryUsage(*index);
 | 
| +    }
 | 
| +
 | 
| +    // TODO(iyengar): Bug 2953
 | 
| +    // Need to verify if this is still true.
 | 
| +    // The automation crashes periodically if we cycle too quickly.
 | 
| +    // To make these tests more reliable, slowing them down a bit.
 | 
| +    Sleep(200);
 | 
| +
 | 
| +    std::string url;
 | 
| +    bool next_url = GetNextUrl(&url);
 | 
| +    if (!url.empty()) {
 | 
| +      NavigateImpl(url);
 | 
| +    } else {
 | 
| +      TestCompleted();
 | 
| +    }
 | 
| +  }
 | 
| +
 | 
| +  void PrintResults(const char* test_name) {
 | 
| +    PrintMemoryUsageInfo(test_name);
 | 
| +    memory_consumption_map_.clear();
 | 
| +
 | 
| +    // Added to give the OS some time to flush the used pages for the
 | 
| +    // chrome processes which would have exited by now.
 | 
| +    Sleep(200);
 | 
| +
 | 
| +    size_t end_commit_charge = GetSystemCommitCharge();
 | 
| +    size_t commit_size = end_commit_charge - start_commit_charge_;
 | 
| +
 | 
| +    std::string trace_name(test_name);
 | 
| +    trace_name.append("_cc");
 | 
| +
 | 
| +    PrintResult("commit_charge", "", trace_name,
 | 
| +                commit_size / 1024, "KB", true /* important */);
 | 
| +    printf("\n");
 | 
| +  }
 | 
| +
 | 
| +  ChromeProcessList GetBrowserChildren() {
 | 
| +    ChromeProcessList list = GetRunningChromeProcesses(user_data_dir_);
 | 
| +    ChromeProcessList::iterator browser =
 | 
| +        std::find(list.begin(), list.end(), browser_pid_);
 | 
| +    if (browser != list.end()) {
 | 
| +      list.erase(browser);
 | 
| +    }
 | 
| +    return list;
 | 
| +  }
 | 
| +
 | 
| +  void AccountProcessMemoryUsage(DWORD process_id) {
 | 
| +    ProcessMemoryInfo process_memory_info(process_id,
 | 
| +                                          process_id == browser_pid_, this);
 | 
| +
 | 
| +    ASSERT_TRUE(process_memory_info.GetMemoryConsumptionDetails());
 | 
| +
 | 
| +    memory_consumption_map_[process_id] = process_memory_info;
 | 
| +  }
 | 
| +
 | 
| +  void PrintMemoryUsageInfo(const char* test_name) {
 | 
| +    printf("\n");
 | 
| +
 | 
| +    std::string trace_name(test_name);
 | 
| +
 | 
| +    ProcessMemoryConsumptionMap::iterator index;
 | 
| +    size_t total_virtual_size = 0;
 | 
| +    size_t total_working_set_size = 0;
 | 
| +
 | 
| +    for (index = memory_consumption_map_.begin();
 | 
| +         index != memory_consumption_map_.end();
 | 
| +         ++index) {
 | 
| +      ProcessMemoryInfo& memory_info = (*index).second;
 | 
| +      memory_info.Print(test_name);
 | 
| +
 | 
| +      total_virtual_size += memory_info.virtual_size_;
 | 
| +      total_working_set_size += memory_info.working_set_size_;
 | 
| +    }
 | 
| +
 | 
| +    printf("\n");
 | 
| +
 | 
| +    PrintResult("vm_final_total", "", trace_name + "_vm",
 | 
| +                total_virtual_size / 1024, "KB",
 | 
| +                false /* not important */);
 | 
| +    PrintResult("ws_final_total", "", trace_name + "_ws",
 | 
| +                total_working_set_size / 1024, "KB",
 | 
| +                true /* important */);
 | 
| +  }
 | 
| +
 | 
| +  // Should never get called.
 | 
| +  virtual void StartTest(const std::string& url,
 | 
| +                         const std::string& test_name) = 0 {
 | 
| +    ASSERT_FALSE(false);
 | 
| +  }
 | 
| +
 | 
| +  // Should never get called.
 | 
| +  virtual void NavigateImpl(const std::string& url) = 0 {
 | 
| +    ASSERT_FALSE(false);
 | 
| +  }
 | 
| +
 | 
| +  virtual void TestCompleted() = 0 {
 | 
| +    ASSERT_FALSE(false);
 | 
| +  }
 | 
| +
 | 
| +  // Holds the commit charge at the start of the memory test run.
 | 
| +  size_t start_commit_charge_;
 | 
| +
 | 
| +  // The index of the URL being tested.
 | 
| +  size_t current_url_index_;
 | 
| +
 | 
| +  // The chrome browser pid.
 | 
| +  base::ProcessId browser_pid_;
 | 
| +
 | 
| +  // Contains the list of urls against which the tests are run.
 | 
| +  std::vector<std::string> urls_;
 | 
| +
 | 
| +  ProcessMemoryConsumptionMap memory_consumption_map_;
 | 
| +};
 | 
| +
 | 
| +// This class provides functionality to run the memory test against a reference
 | 
| +// chrome frame build.
 | 
| +class ChromeFrameMemoryTestReference : public ChromeFrameMemoryTest {
 | 
| + public:
 | 
| +  virtual void SetUp() {
 | 
| +    chrome_frame_registrar_.reset(new ScopedChromeFrameRegistrar);
 | 
| +    chrome_frame_registrar_->RegisterReferenceChromeFrameBuild();
 | 
| +  }
 | 
| +
 | 
| +  virtual void TearDown() {
 | 
| +    // Reregisters the chrome frame DLL in the build directory.
 | 
| +    chrome_frame_registrar_.reset(NULL);
 | 
| +  }
 | 
| +};
 | 
| +
 | 
| +// This class overrides the hooks provided by the ChromeFrameActiveXContainer
 | 
| +// class and calls back into the ChromeFrameMemoryTest object instance,
 | 
| +// which measures ChromeFrame memory usage.
 | 
| +class ChromeFrameActiveXContainerMemory : public ChromeFrameActiveXContainer {
 | 
| + public:
 | 
| +  ChromeFrameActiveXContainerMemory()
 | 
| +      : delegate_(NULL) {}
 | 
| +
 | 
| +  ~ChromeFrameActiveXContainerMemory() {}
 | 
| +
 | 
| +  void Initialize(ChromeFrameMemoryTest* delegate) {
 | 
| +    ASSERT_TRUE(delegate != NULL);
 | 
| +    delegate_ = delegate;
 | 
| +  }
 | 
| +
 | 
| + protected:
 | 
| +  virtual void OnLoadCallbackImpl(VARIANT* param) {
 | 
| +    delegate_->OnNavigationSuccess(param);
 | 
| +  }
 | 
| +
 | 
| +  virtual void OnLoadErrorCallbackImpl(VARIANT* param) {
 | 
| +    delegate_->OnNavigationFailure(param);
 | 
| +  }
 | 
| +
 | 
| +  ChromeFrameMemoryTest* delegate_;
 | 
| +};
 | 
| +
 | 
| +// This class runs memory tests against the ChromeFrame ActiveX.
 | 
| +template<class MemoryTestBase>
 | 
| +class ChromeFrameActiveXMemoryTest : public MemoryTestBase {
 | 
| + public:
 | 
| +  ChromeFrameActiveXMemoryTest()
 | 
| +      : chrome_frame_container_(NULL),
 | 
| +        test_completed_(false) {}
 | 
| +
 | 
| +  ~ChromeFrameActiveXMemoryTest() {
 | 
| +  }
 | 
| +
 | 
| +  void StartTest(const std::string& url, const std::string& test_name) {
 | 
| +    ASSERT_TRUE(chrome_frame_container_ == NULL);
 | 
| +
 | 
| +    test_name_ = test_name;
 | 
| +
 | 
| +    SimpleModule module;
 | 
| +    AtlAxWinInit();
 | 
| +
 | 
| +    CComObject<ChromeFrameActiveXContainerMemory>::CreateInstance(
 | 
| +        &chrome_frame_container_);
 | 
| +    chrome_frame_container_->AddRef();
 | 
| +
 | 
| +    chrome_frame_container_->Initialize(this);
 | 
| +
 | 
| +    chrome_frame_container_->CreateChromeFrameWindow(url.c_str());
 | 
| +    chrome_frame_container_->CreateControl(true);
 | 
| +
 | 
| +    module.RunMessageLoop();
 | 
| +
 | 
| +    chrome_frame_container_->Release();
 | 
| +
 | 
| +    PrintResults(test_name_.c_str());
 | 
| +
 | 
| +    CoFreeUnusedLibraries();
 | 
| +    //ASSERT_TRUE(GetModuleHandle(L"npchrome_tab.dll") == NULL);
 | 
| +  }
 | 
| +
 | 
| +  void NavigateImpl(const std::string& url) {
 | 
| +    ASSERT_TRUE(chrome_frame_container_ != NULL);
 | 
| +    ASSERT_TRUE(!url.empty());
 | 
| +    chrome_frame_container_->Navigate(url.c_str());
 | 
| +  }
 | 
| +
 | 
| +  void TestCompleted() {
 | 
| +    // This can get called multiple times if the last url results in a
 | 
| +    // redirect.
 | 
| +    if (!test_completed_) {
 | 
| +      ASSERT_NE(browser_pid_, 0);
 | 
| +
 | 
| +      // Measure memory usage for the browser process.
 | 
| +      AccountProcessMemoryUsage(browser_pid_);
 | 
| +      // Measure memory usage for the current process.
 | 
| +      AccountProcessMemoryUsage(GetCurrentProcessId());
 | 
| +
 | 
| +      test_completed_ = true;
 | 
| +      EXPECT_TRUE(PostMessage(static_cast<HWND>(*chrome_frame_container_),
 | 
| +                              WM_CLOSE, 0, 0));
 | 
| +    }
 | 
| +  }
 | 
| +
 | 
| + protected:
 | 
| +  CComObject<ChromeFrameActiveXContainerMemory>* chrome_frame_container_;
 | 
| +  std::string test_name_;
 | 
| +  bool test_completed_;
 | 
| +};
 | 
| +
 | 
| +// This class runs tests to measure chrome frame creation only. This will help
 | 
| +// track overall page load performance with chrome frame instances.
 | 
| +class ChromeFrameCreationTest : public ChromeFrameStartupTest {
 | 
| + protected:
 | 
| +  virtual void RunStartupTestImpl(TimeTicks* start_time,
 | 
| +                                  TimeTicks* end_time) {
 | 
| +    SimpleModule module;
 | 
| +    AtlAxWinInit();
 | 
| +    CComObjectStackEx<ChromeFrameActiveXContainer> wnd;
 | 
| +    wnd.CreateChromeFrameWindow(startup_url_);
 | 
| +    *start_time = TimeTicks::Now();
 | 
| +    wnd.CreateControl(false);
 | 
| +    *end_time = TimeTicks::Now();
 | 
| +  }
 | 
| +};
 | 
| +
 | 
| +// This class provides functionality to run the chrome frame
 | 
| +// performance test against a reference build.
 | 
| +class ChromeFrameCreationTestReference : public ChromeFrameCreationTest {
 | 
| + public:
 | 
| +  // override the browser directory to use the reference build instead.
 | 
| +  virtual void SetUp() {
 | 
| +    chrome_frame_registrar_.reset(new ScopedChromeFrameRegistrar);
 | 
| +    chrome_frame_registrar_->RegisterReferenceChromeFrameBuild();
 | 
| +    ChromeFrameStartupTest::SetUp();
 | 
| +  }
 | 
| +
 | 
| +  virtual void TearDown() {
 | 
| +    chrome_frame_registrar_.reset(NULL);
 | 
| +  }
 | 
| +};
 | 
| +
 | 
| +// This class measures the creation time for Flash, which would be used
 | 
| +// as a baseline to measure chrome frame creation performance.
 | 
| +class FlashCreationTest : public ChromeFrameStartupTest {
 | 
| + protected:
 | 
| +  virtual void RunStartupTestImpl(TimeTicks* start_time,
 | 
| +                                  TimeTicks* end_time) {
 | 
| +    SimpleModule module;
 | 
| +    AtlAxWinInit();
 | 
| +    CAxWindow host;
 | 
| +    RECT rc = {0, 0, 800, 600};
 | 
| +    host.Create(NULL, rc, NULL,
 | 
| +        WS_OVERLAPPEDWINDOW | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
 | 
| +        WS_EX_APPWINDOW | WS_EX_WINDOWEDGE);
 | 
| +    EXPECT_TRUE(host.m_hWnd != NULL);
 | 
| +
 | 
| +    *start_time = TimeTicks::Now();
 | 
| +    HRESULT hr = host.CreateControl(L"ShockwaveFlash.ShockwaveFlash");
 | 
| +    EXPECT_HRESULT_SUCCEEDED(hr);
 | 
| +    *end_time = TimeTicks::Now();
 | 
| +
 | 
| +    ReleaseHostComReferences(host);
 | 
| +  }
 | 
| +};
 | 
| +
 | 
| +// This class measures the creation time for Silverlight, which would be used
 | 
| +// as a baseline to measure chrome frame creation performance.
 | 
| +class SilverlightCreationTest : public ChromeFrameStartupTest {
 | 
| + protected:
 | 
| +  virtual void RunStartupTestImpl(TimeTicks* start_time,
 | 
| +                                  TimeTicks* end_time) {
 | 
| +    SimpleModule module;
 | 
| +    AtlAxWinInit();
 | 
| +    CAxWindow host;
 | 
| +    RECT rc = {0, 0, 800, 600};
 | 
| +    host.Create(NULL, rc, NULL,
 | 
| +        WS_OVERLAPPEDWINDOW | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
 | 
| +        WS_EX_APPWINDOW | WS_EX_WINDOWEDGE);
 | 
| +    EXPECT_TRUE(host.m_hWnd != NULL);
 | 
| +
 | 
| +    *start_time = TimeTicks::Now();
 | 
| +    HRESULT hr = host.CreateControl(L"AgControl.AgControl");
 | 
| +    EXPECT_HRESULT_SUCCEEDED(hr);
 | 
| +    *end_time = TimeTicks::Now();
 | 
| +
 | 
| +    ReleaseHostComReferences(host);
 | 
| +  }
 | 
| +};
 | 
| +
 | 
| +TEST(ChromeFramePerf, DISABLED_HostActiveX) {
 | 
| +  // TODO(stoyan): Create a low integrity level thread && perform the test there
 | 
| +  SimpleModule module;
 | 
| +  AtlAxWinInit();
 | 
| +  CComObjectStackEx<ChromeFrameActiveXContainerPerf> wnd;
 | 
| +  wnd.CreateChromeFrameWindow("http://www.google.com");
 | 
| +  wnd.CreateControl(true);
 | 
| +  module.RunMessageLoop();
 | 
| +}
 | 
| +
 | 
| +TEST(ChromeFramePerf, DISABLED_HostActiveXInvalidURL) {
 | 
| +  // TODO(stoyan): Create a low integrity level thread && perform the test there
 | 
| +  SimpleModule module;
 | 
| +  AtlAxWinInit();
 | 
| +  CComObjectStackEx<ChromeFrameActiveXContainerPerf> wnd;
 | 
| +  wnd.CreateChromeFrameWindow("http://non-existent-domain.org/");
 | 
| +  wnd.CreateControl(true);
 | 
| +  module.RunMessageLoop();
 | 
| +}
 | 
| +
 | 
| +TEST_F(ChromeFrameStartupTestActiveX, PerfWarm) {
 | 
| +  RunStartupTest("warm", "t", "about:blank", false /* cold */, 0, NULL,
 | 
| +                 true /* important */, false);
 | 
| +}
 | 
| +
 | 
| +TEST_F(ChromeFrameBinariesLoadTest, PerfWarm) {
 | 
| +  RunStartupTest("binary_load_warm", "t", "", false /* cold */, 0, NULL,
 | 
| +                 true /* important */, false);
 | 
| +}
 | 
| +
 | 
| +TEST_F(ChromeFrameStartupTestActiveX, PerfCold) {
 | 
| +  FilePath binaries_to_evict[] = {chrome_exe_, chrome_dll_, chrome_frame_dll_};
 | 
| +  RunStartupTest("cold", "t", "about:blank", true /* cold */,
 | 
| +                 arraysize(binaries_to_evict), binaries_to_evict,
 | 
| +                 false /* not important */, false);
 | 
| +}
 | 
| +
 | 
| +TEST_F(ChromeFrameBinariesLoadTest, PerfCold) {
 | 
| +  FilePath binaries_to_evict[] = {chrome_exe_, chrome_dll_, chrome_frame_dll_};
 | 
| +  RunStartupTest("binary_load_cold", "t", "", true /* cold */,
 | 
| +                 arraysize(binaries_to_evict), binaries_to_evict,
 | 
| +                 false /* not important */, false);
 | 
| +}
 | 
| +
 | 
| +TEST_F(ChromeFrameStartupTestActiveXReference, PerfWarm) {
 | 
| +  RunStartupTest("warm", "t_ref", "about:blank", false /* cold */, 0, NULL,
 | 
| +                 true /* important */, false);
 | 
| +}
 | 
| +
 | 
| +TEST_F(ChromeFrameStartupTestActiveX, PerfChromeFrameInitializationWarm) {
 | 
| +  RunStartupTest("ChromeFrame_init_warm", "t", "", false /* cold */, 0,
 | 
| +                 NULL, true /* important */, false);
 | 
| +}
 | 
| +
 | 
| +TEST_F(ChromeFrameStartupTestActiveX, PerfChromeFrameInitializationCold) {
 | 
| +  FilePath binaries_to_evict[] = {chrome_frame_dll_};
 | 
| +  RunStartupTest("ChromeFrame_init_cold", "t", "", true /* cold */,
 | 
| +                 arraysize(binaries_to_evict), binaries_to_evict,
 | 
| +                 false /* not important */, false);
 | 
| +}
 | 
| +
 | 
| +TEST_F(ChromeFrameStartupTestActiveXReference,
 | 
| +       PerfChromeFrameInitializationWarm) {
 | 
| +  RunStartupTest("ChromeFrame_init_warm", "t_ref", "", false /* cold */, 0,
 | 
| +                 NULL, true /* important */, false);
 | 
| +}
 | 
| +
 | 
| +typedef ChromeFrameActiveXMemoryTest<ChromeFrameMemoryTest>
 | 
| +    RegularChromeFrameActiveXMemoryTest;
 | 
| +
 | 
| +TEST_F(RegularChromeFrameActiveXMemoryTest, MemoryTestAboutBlank) {
 | 
| +  char *urls[] = {"about:blank"};
 | 
| +  RunTest("memory_about_blank", urls, arraysize(urls));
 | 
| +}
 | 
| +
 | 
| +// TODO(iyengar)
 | 
| +// Revisit why the chrome frame dll does not unload correctly when this test is
 | 
| +// run.
 | 
| +TEST_F(RegularChromeFrameActiveXMemoryTest, DISABLED_MemoryTestUrls) {
 | 
| +  // TODO(iyengar)
 | 
| +  // We should use static pages to measure memory usage.
 | 
| +  char *urls[] = {
 | 
| +    "http://www.youtube.com/watch?v=PN2HAroA12w",
 | 
| +    "http://www.youtube.com/watch?v=KmLJDrsaJmk&feature=channel"
 | 
| +  };
 | 
| +
 | 
| +  RunTest("memory", urls, arraysize(urls));
 | 
| +}
 | 
| +
 | 
| +typedef ChromeFrameActiveXMemoryTest<ChromeFrameMemoryTestReference>
 | 
| +    ReferenceBuildChromeFrameActiveXMemoryTest;
 | 
| +
 | 
| +TEST_F(ReferenceBuildChromeFrameActiveXMemoryTest, MemoryTestAboutBlank) {
 | 
| +  char *urls[] = {"about:blank"};
 | 
| +  RunTest("memory_about_blank_reference", urls, arraysize(urls));
 | 
| +}
 | 
| +
 | 
| +// TODO(iyengar)
 | 
| +// Revisit why the chrome frame dll does not unload correctly when this test is
 | 
| +// run.
 | 
| +TEST_F(ReferenceBuildChromeFrameActiveXMemoryTest, DISABLED_MemoryTestUrls) {
 | 
| +  // TODO(iyengar)
 | 
| +  // We should use static pages to measure memory usage.
 | 
| +  char *urls[] = {
 | 
| +    "http://www.youtube.com/watch?v=PN2HAroA12w",
 | 
| +    "http://www.youtube.com/watch?v=KmLJDrsaJmk&feature=channel"
 | 
| +  };
 | 
| +
 | 
| +  RunTest("memory_reference", urls, arraysize(urls));
 | 
| +}
 | 
| +
 | 
| +TEST_F(ChromeFrameCreationTest, PerfWarm) {
 | 
| +  RunStartupTest("creation_warm", "t", "", false /* cold */, 0,
 | 
| +                 NULL, true /* important */, false);
 | 
| +}
 | 
| +
 | 
| +TEST_F(ChromeFrameCreationTestReference, PerfWarm) {
 | 
| +  RunStartupTest("creation_warm", "t_ref", "about:blank", false /* cold */, 0,
 | 
| +                 NULL, true /* not important */, false);
 | 
| +}
 | 
| +
 | 
| +TEST_F(FlashCreationTest, PerfWarm) {
 | 
| +  RunStartupTest("creation_warm", "t_flash", "", false /* cold */, 0, NULL,
 | 
| +                 true /* not important */, false);
 | 
| +}
 | 
| +
 | 
| +TEST_F(SilverlightCreationTest, DISABLED_PerfWarm) {
 | 
| +  RunStartupTest("creation_warm", "t_silverlight", "", false /* cold */, 0,
 | 
| +                 NULL, false /* not important */, false);
 | 
| +}
 | 
| +
 | 
| +TEST_F(ChromeFrameCreationTest, PerfCold) {
 | 
| +  FilePath binaries_to_evict[] = {chrome_frame_dll_};
 | 
| +
 | 
| +  RunStartupTest("creation_cold", "t", "", true /* cold */,
 | 
| +                 arraysize(binaries_to_evict), binaries_to_evict,
 | 
| +                 true /* important */, false);
 | 
| +}
 | 
| +
 | 
| +// Attempt to evict the Flash control can fail on the buildbot as the dll
 | 
| +// is marked read only. The test run is aborted if we fail to evict the file
 | 
| +// from the cache. This could also fail if the Flash control is in use.
 | 
| +// On Vista this could fail because of UAC
 | 
| +TEST_F(FlashCreationTest, PerfCold) {
 | 
| +  RegKey flash_key(HKEY_CLASSES_ROOT, kFlashControlKey);
 | 
| +
 | 
| +  std::wstring plugin_path;
 | 
| +  ASSERT_TRUE(flash_key.ReadValue(L"", &plugin_path));
 | 
| +  ASSERT_FALSE(plugin_path.empty());
 | 
| +
 | 
| +  FilePath flash_path = FilePath::FromWStringHack(plugin_path);
 | 
| +  FilePath binaries_to_evict[] = {flash_path};
 | 
| +
 | 
| +  RunStartupTest("creation_cold", "t_flash", "", true /* cold */,
 | 
| +                 arraysize(binaries_to_evict), binaries_to_evict,
 | 
| +                 false/* important */, true);
 | 
| +}
 | 
| +
 | 
| +// This test would fail on Vista due to UAC or if the Silverlight control is
 | 
| +// in use. The test run is aborted if we fail to evict the file from the cache.
 | 
| +// Disabling this test as the Silverlight dll does not seem to get unloaded
 | 
| +// correctly causing the attempt to evict the dll from the system cache to
 | 
| +// fail.
 | 
| +TEST_F(SilverlightCreationTest, DISABLED_PerfCold) {
 | 
| +  RegKey silverlight_key(HKEY_CLASSES_ROOT, kSilverlightControlKey);
 | 
| +
 | 
| +  std::wstring plugin_path;
 | 
| +  ASSERT_TRUE(silverlight_key.ReadValue(L"", &plugin_path));
 | 
| +  ASSERT_FALSE(plugin_path.empty());
 | 
| +
 | 
| +  FilePath silverlight_path = FilePath::FromWStringHack(plugin_path);
 | 
| +  FilePath binaries_to_evict[] = {silverlight_path};
 | 
| +
 | 
| +  RunStartupTest("creation_cold", "t_silverlight", "", true /* cold */,
 | 
| +                 arraysize(binaries_to_evict), binaries_to_evict,
 | 
| +                 false /* important */, true);
 | 
| +}
 | 
| 
 |