summaryrefslogtreecommitdiffstats
path: root/tools/measure_page_load_time
diff options
context:
space:
mode:
authorinitial.commit <initial.commit@0039d316-1c4b-4281-b951-d872f2087c98>2008-07-27 00:12:16 +0000
committerinitial.commit <initial.commit@0039d316-1c4b-4281-b951-d872f2087c98>2008-07-27 00:12:16 +0000
commit920c091ac3ee15079194c82ae8a7a18215f3f23c (patch)
treed28515d1e7732e2b6d077df1b4855ace3f4ac84f /tools/measure_page_load_time
parentae2c20f398933a9e86c387dcc465ec0f71065ffc (diff)
downloadchromium_src-920c091ac3ee15079194c82ae8a7a18215f3f23c.zip
chromium_src-920c091ac3ee15079194c82ae8a7a18215f3f23c.tar.gz
chromium_src-920c091ac3ee15079194c82ae8a7a18215f3f23c.tar.bz2
Add tools to the repository.
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@17 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'tools/measure_page_load_time')
-rw-r--r--tools/measure_page_load_time/ff_ext/chrome.manifest2
-rw-r--r--tools/measure_page_load_time/ff_ext/content/firefoxOverlay.xul7
-rw-r--r--tools/measure_page_load_time/ff_ext/content/measure_page_load_time.js207
-rw-r--r--tools/measure_page_load_time/ff_ext/install.rdf17
-rw-r--r--tools/measure_page_load_time/ie_bho/MeasurePageLoadTime.cpp97
-rw-r--r--tools/measure_page_load_time/ie_bho/MeasurePageLoadTime.def9
-rw-r--r--tools/measure_page_load_time/ie_bho/MeasurePageLoadTime.idl65
-rw-r--r--tools/measure_page_load_time/ie_bho/MeasurePageLoadTime.rc121
-rw-r--r--tools/measure_page_load_time/ie_bho/MeasurePageLoadTime.rgs29
-rw-r--r--tools/measure_page_load_time/ie_bho/MeasurePageLoadTime.vcproj320
-rw-r--r--tools/measure_page_load_time/ie_bho/MeasurePageLoadTimeBHO.cpp317
-rw-r--r--tools/measure_page_load_time/ie_bho/MeasurePageLoadTimeBHO.h113
-rw-r--r--tools/measure_page_load_time/ie_bho/MeasurePageLoadTimeBHO.rgs27
-rw-r--r--tools/measure_page_load_time/ie_bho/resource.h18
-rw-r--r--tools/measure_page_load_time/ie_bho/stdafx.cpp5
-rw-r--r--tools/measure_page_load_time/ie_bho/stdafx.h39
16 files changed, 1393 insertions, 0 deletions
diff --git a/tools/measure_page_load_time/ff_ext/chrome.manifest b/tools/measure_page_load_time/ff_ext/chrome.manifest
new file mode 100644
index 0000000..9e1d73d4
--- /dev/null
+++ b/tools/measure_page_load_time/ff_ext/chrome.manifest
@@ -0,0 +1,2 @@
+content measurepageloadtimeextension content/
+overlay chrome://browser/content/browser.xul chrome://measurepageloadtimeextension/content/firefoxOverlay.xul
diff --git a/tools/measure_page_load_time/ff_ext/content/firefoxOverlay.xul b/tools/measure_page_load_time/ff_ext/content/firefoxOverlay.xul
new file mode 100644
index 0000000..1c5529e
--- /dev/null
+++ b/tools/measure_page_load_time/ff_ext/content/firefoxOverlay.xul
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?xml-stylesheet href="chrome://measurepageloadtimeextension/skin/overlay.css" type="text/css"?>
+<!DOCTYPE overlay SYSTEM "chrome://measurepageloadtimeextension/locale/measurepageloadtimeextension.dtd">
+<overlay id="measurepageloadtimeextension-overlay"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+ <script src="measure_page_load_time.js"/>
+</overlay>
diff --git a/tools/measure_page_load_time/ff_ext/content/measure_page_load_time.js b/tools/measure_page_load_time/ff_ext/content/measure_page_load_time.js
new file mode 100644
index 0000000..d9a6ca6
--- /dev/null
+++ b/tools/measure_page_load_time/ff_ext/content/measure_page_load_time.js
@@ -0,0 +1,207 @@
+// Copyright 2008 Google Inc.
+// All Rights Reserved.
+/**
+ * @fileoverview measure_page_load_time.js implements a Firefox extension
+ * for measuring how long a page takes to load. It waits on TCP port
+ * 42492 for connections, then accepts URLs and returns strings of the
+ * form url,time, where "time" is the load time in milliseconds or the
+ * string "timeout" or "error". Load time is measured from the call to
+ * loadURI until the load event fires, or until the status changes to
+ * STATUS_STOP if the load event doesn't fire (there's an error.)
+ * @author jhaas@google.com (Jonathan Haas) */
+
+// Shorthand reference to nsIWebProgress[Listener] interfaces
+var IWP = Components.interfaces.nsIWebProgress;
+var IWPL = Components.interfaces.nsIWebProgressListener;
+
+
+var MPLT = {
+ /**
+ * Constants
+ */
+ PORT_NUMBER : 42492, // port to listen for connections on
+ TIME_OUT : 4 * 60 * 1000, // timeout in 4 minutes
+
+ /**
+ * Incoming URL buffer
+ * @type {string}
+ */
+ textBuffer : '',
+
+ /**
+ * URL we're currently visiting
+ * @type {string}
+ */
+ URL : '',
+
+ /**
+ * Listener to accept incoming connections
+ * @type {nsIServerSocketListener}
+ */
+ acceptListener :
+ {
+ onSocketAccepted : function(serverSocket, transport)
+ {
+ MPLT.streamInput = transport.openInputStream(0,0,0);
+ MPLT.streamOutput = transport.openOutputStream(0,0,0);
+
+ MPLT.scriptStream = Components.classes['@mozilla.org/scriptableinputstream;1']
+ .createInstance(Components.interfaces.nsIScriptableInputStream);
+ MPLT.scriptStream.init(MPLT.streamInput);
+ MPLT.pump = Components.classes['@mozilla.org/network/input-stream-pump;1']
+ .createInstance(Components.interfaces.nsIInputStreamPump);
+ MPLT.pump.init(MPLT.streamInput, -1, -1, 0, 0, false);
+ MPLT.pump.asyncRead(MPLT.dataListener,null);
+ },
+
+ onStopListening : function(){}
+ },
+
+ /**
+ * Listener for network input
+ * @type {nsIStreamListener}
+ */
+ dataListener :
+ {
+ onStartRequest: function(){},
+ onStopRequest: function(){},
+ onDataAvailable: function(request, context, inputStream, offset, count){
+ // Add the received data to the buffer, then process it
+ // Change CRLF to newline while we're at it
+ MPLT.textBuffer += MPLT.scriptStream.read(count).replace('\r\n', '\n');
+
+ MPLT.process();
+ }
+ },
+
+ /**
+ * Process the incoming data buffer
+ */
+ process : function()
+ {
+ // If we're waiting for a page to finish loading, wait
+ if (MPLT.timeLoadStarted)
+ return;
+
+ // Look for a carriage return
+ var firstCR = MPLT.textBuffer.indexOf('\n');
+
+ // If we haven't received a carriage return yet, wait
+ if (firstCR < 0)
+ return;
+
+ // If the first character was a carriage return, we're done!
+ if (firstCR == 0) {
+ MPLT.textBuffer = '';
+ MPLT.streamInput.close();
+ MPLT.streamOutput.close();
+
+ return;
+ }
+
+ // Remove the URL from the buffer
+ MPLT.URL = MPLT.textBuffer.substr(0, firstCR);
+ MPLT.textBuffer = MPLT.textBuffer.substr(firstCR + 1);
+
+ // Remember the current time and navigate to the new URL
+ MPLT.timeLoadStarted = new Date();
+ gBrowser.loadURIWithFlags(MPLT.URL, gBrowser.LOAD_FLAGS_BYPASS_CACHE);
+ setTimeout('MPLT.onTimeOut()', MPLT.TIME_OUT);
+ },
+
+ /**
+ * Page load completion handler
+ */
+ onPageLoad : function(e) {
+ // Ignore loads of non-HTML documents
+ if (!(e.originalTarget instanceof HTMLDocument))
+ return;
+
+ // Also ignore subframe loads
+ if (e.originalTarget.defaultView.frameElement)
+ return;
+
+ clearTimeout();
+ var timeElapsed = new Date() - MPLT.timeLoadStarted;
+
+ MPLT.outputResult(timeElapsed);
+ },
+
+ /**
+ * Timeout handler
+ */
+ onTimeOut : function() {
+ gBrowser.stop();
+
+ MPLT.outputResult('timeout');
+ },
+
+
+ /**
+ * Sends a properly-formatted result to the client
+ * @param {string} result The value to send along with the URL
+ */
+ outputResult : function(result) {
+
+ if (MPLT.URL) {
+ var outputString = MPLT.URL + ',' + result + '\n';
+ MPLT.streamOutput.write(outputString, outputString.length);
+ MPLT.URL = '';
+ }
+
+ MPLT.timeLoadStarted = null;
+ MPLT.process();
+ },
+
+ /**
+ * Time the page load started. If null, we're waiting for the
+ * initial page load, or otherwise don't care about the page
+ * that's currently loading
+ * @type {number}
+ */
+ timeLoadStarted : null,
+
+ /*
+ * TODO(jhaas): add support for nsIWebProgressListener
+ * If the URL being visited died as part of a network error
+ * (host not found, connection reset by peer, etc), the onload
+ * event doesn't fire. The only way to catch it would be in
+ * a web progress listener. However, nsIWebProgress is not
+ * behaving according to documentation. More research is needed.
+ * For now, omitting it means that if any of our URLs are "dirty"
+ * (do not point to real web servers with real responses), we'll log
+ * them as timeouts. This doesn't affect pages where the server
+ * exists but returns an error code.
+ */
+
+ /**
+ * Initialize the plugin, create the socket and listen
+ */
+ initialize: function() {
+ // Register for page load events
+ gBrowser.addEventListener('load', this.onPageLoad, true);
+
+ // Set a timeout to wait for the initial page to load
+ MPLT.timeLoadStarted = new Date();
+ setTimeout('MPLT.onTimeOut()', MPLT.TIME_OUT);
+
+ // Create the listening socket
+ MPLT.serverSocket = Components.classes['@mozilla.org/network/server-socket;1']
+ .createInstance(Components.interfaces.nsIServerSocket);
+
+ MPLT.serverSocket.init(MPLT.PORT_NUMBER, true, 1);
+ MPLT.serverSocket.asyncListen(this.acceptListener);
+ },
+
+ /**
+ * Close the socket(s)
+ */
+ deinitialize: function() {
+ if (MPLT.streamInput) MPLT.streamInput.close();
+ if (MPLT.streamOutput) MPLT.streamOutput.close();
+ if (MPLT.serverSocket) MPLT.serverSocket.close();
+ }
+};
+
+window.addEventListener('load', function(e) { MPLT.initialize(); }, false);
+window.addEventListener('unload', function(e) { MPLT.deinitialize(); }, false);
diff --git a/tools/measure_page_load_time/ff_ext/install.rdf b/tools/measure_page_load_time/ff_ext/install.rdf
new file mode 100644
index 0000000..70d510a
--- /dev/null
+++ b/tools/measure_page_load_time/ff_ext/install.rdf
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:em="http://www.mozilla.org/2004/em-rdf#">
+ <Description about="urn:mozilla:install-manifest">
+ <em:id>measurepageloadtimeextension@google.com</em:id>
+ <em:name>MeasurePageLoadTime</em:name>
+ <em:version>1.0</em:version>
+ <em:creator>Jonathan Haas</em:creator>
+ <em:targetApplication>
+ <Description>
+ <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id> <!-- firefox -->
+ <em:minVersion>1.5</em:minVersion>
+ <em:maxVersion>2.0.0.*</em:maxVersion>
+ </Description>
+ </em:targetApplication>
+ </Description>
+</RDF>
diff --git a/tools/measure_page_load_time/ie_bho/MeasurePageLoadTime.cpp b/tools/measure_page_load_time/ie_bho/MeasurePageLoadTime.cpp
new file mode 100644
index 0000000..55f4de2
--- /dev/null
+++ b/tools/measure_page_load_time/ie_bho/MeasurePageLoadTime.cpp
@@ -0,0 +1,97 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// MeasurePageLoadTime.cpp : Implementation of DLL Exports.
+
+#include "stdafx.h"
+#include "resource.h"
+#include "MeasurePageLoadTime.h"
+
+
+class CMeasurePageLoadTimeModule : public CAtlDllModuleT< CMeasurePageLoadTimeModule >
+{
+public :
+ DECLARE_LIBID(LIBID_MeasurePageLoadTimeLib)
+ DECLARE_REGISTRY_APPID_RESOURCEID(IDR_MEASUREPAGELOADTIME, "{56C6D9F9-643C-4F6E-906C-5F7CECB23C24}")
+};
+
+CMeasurePageLoadTimeModule _AtlModule;
+
+
+#ifdef _MANAGED
+#pragma managed(push, off)
+#endif
+
+// DLL Entry Point
+extern "C" BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
+{
+ if (dwReason == DLL_PROCESS_ATTACH)
+ {
+ DisableThreadLibraryCalls(hInstance);
+ }
+ return _AtlModule.DllMain(dwReason, lpReserved);
+}
+
+#ifdef _MANAGED
+#pragma managed(pop)
+#endif
+
+
+
+
+// Used to determine whether the DLL can be unloaded by OLE
+STDAPI DllCanUnloadNow(void)
+{
+ return _AtlModule.DllCanUnloadNow();
+}
+
+
+// Returns a class factory to create an object of the requested type
+STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv)
+{
+ return _AtlModule.DllGetClassObject(rclsid, riid, ppv);
+}
+
+
+// DllRegisterServer - Adds entries to the system registry
+STDAPI DllRegisterServer(void)
+{
+ // registers object, typelib and all interfaces in typelib
+ HRESULT hr = _AtlModule.DllRegisterServer();
+ return hr;
+}
+
+
+// DllUnregisterServer - Removes entries from the system registry
+STDAPI DllUnregisterServer(void)
+{
+ HRESULT hr = _AtlModule.DllUnregisterServer();
+ return hr;
+}
+
diff --git a/tools/measure_page_load_time/ie_bho/MeasurePageLoadTime.def b/tools/measure_page_load_time/ie_bho/MeasurePageLoadTime.def
new file mode 100644
index 0000000..5552923
--- /dev/null
+++ b/tools/measure_page_load_time/ie_bho/MeasurePageLoadTime.def
@@ -0,0 +1,9 @@
+; MeasurePageLoadTime.def : Declares the module parameters.
+
+LIBRARY "MeasurePageLoadTime.DLL"
+
+EXPORTS
+ DllCanUnloadNow PRIVATE
+ DllGetClassObject PRIVATE
+ DllRegisterServer PRIVATE
+ DllUnregisterServer PRIVATE
diff --git a/tools/measure_page_load_time/ie_bho/MeasurePageLoadTime.idl b/tools/measure_page_load_time/ie_bho/MeasurePageLoadTime.idl
new file mode 100644
index 0000000..d0c8270
--- /dev/null
+++ b/tools/measure_page_load_time/ie_bho/MeasurePageLoadTime.idl
@@ -0,0 +1,65 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// MeasurePageLoadTime.idl : IDL source for MeasurePageLoadTime
+//
+
+// This file will be processed by the MIDL tool to
+// produce the type library (MeasurePageLoadTime.tlb) and marshalling code.
+
+import "oaidl.idl";
+import "ocidl.idl";
+
+[
+ object,
+ uuid(019637EB-B865-485B-9A66-419477EE55A0),
+ dual,
+ nonextensible,
+ helpstring("IMeasurePageLoadTimeBHO Interface"),
+ pointer_default(unique)
+]
+interface IMeasurePageLoadTimeBHO : IDispatch{
+};
+[
+ uuid(61AC7AC4-B715-4955-A238-5F9AEA80DF4B),
+ version(1.0),
+ helpstring("MeasurePageLoadTime 1.0 Type Library")
+]
+library MeasurePageLoadTimeLib
+{
+ importlib("stdole2.tlb");
+ [
+ uuid(807E68BC-238F-4163-AE4B-0A3604F3E145),
+ helpstring("MeasurePageLoadTimeBHO Class")
+ ]
+ coclass MeasurePageLoadTimeBHO
+ {
+ [default] interface IMeasurePageLoadTimeBHO;
+ };
+};
diff --git a/tools/measure_page_load_time/ie_bho/MeasurePageLoadTime.rc b/tools/measure_page_load_time/ie_bho/MeasurePageLoadTime.rc
new file mode 100644
index 0000000..9285a70
--- /dev/null
+++ b/tools/measure_page_load_time/ie_bho/MeasurePageLoadTime.rc
@@ -0,0 +1,121 @@
+// Microsoft Visual C++ generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "winres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// English (U.S.) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+#ifdef _WIN32
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+#pragma code_page(1252)
+#endif //_WIN32
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE
+BEGIN
+ "#include ""winres.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE
+BEGIN
+ "1 TYPELIB ""MeasurePageLoadTime.tlb""\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version
+//
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION 1,0,0,1
+ PRODUCTVERSION 1,0,0,1
+ FILEFLAGSMASK 0x3fL
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS 0x4L
+ FILETYPE 0x2L
+ FILESUBTYPE 0x0L
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904e4"
+ BEGIN
+ VALUE "CompanyName", "Google"
+ VALUE "FileDescription", "Measures page load times"
+ VALUE "FileVersion", "1.0.0.1"
+ VALUE "LegalCopyright", "(c) 2008 Google. All rights reserved."
+ VALUE "InternalName", "MeasurePageLoadTime.dll"
+ VALUE "OriginalFilename", "MeasurePageLoadTime.dll"
+ VALUE "ProductName", "MeasurePageLoadTime"
+ VALUE "ProductVersion", "1.0.0.1"
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x409, 1252
+ END
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// REGISTRY
+//
+
+IDR_MEASUREPAGELOADTIME REGISTRY "MeasurePageLoadTime.rgs"
+IDR_MEASUREPAGELOADTIMEBHO REGISTRY "MeasurePageLoadTimeBHO.rgs"
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// String Table
+//
+
+STRINGTABLE
+BEGIN
+ IDS_PROJNAME "MeasurePageLoadTime"
+END
+
+#endif // English (U.S.) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+1 TYPELIB "MeasurePageLoadTime.tlb"
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/tools/measure_page_load_time/ie_bho/MeasurePageLoadTime.rgs b/tools/measure_page_load_time/ie_bho/MeasurePageLoadTime.rgs
new file mode 100644
index 0000000..98e7f78
--- /dev/null
+++ b/tools/measure_page_load_time/ie_bho/MeasurePageLoadTime.rgs
@@ -0,0 +1,29 @@
+HKCR
+{
+ NoRemove AppID
+ {
+ '%APPID%' = s 'MeasurePageLoadTime'
+ 'MeasurePageLoadTime.DLL'
+ {
+ val AppID = s '%APPID%'
+ }
+ }
+}
+
+HKLM {
+ NoRemove SOFTWARE {
+ NoRemove Microsoft {
+ NoRemove Windows {
+ NoRemove CurrentVersion {
+ NoRemove Explorer {
+ NoRemove 'Browser Helper Objects' {
+ ForceRemove '{807E68BC-238F-4163-AE4B-0A3604F3E145}' = s 'MeasurePageLoadTimeBHO' {
+ val 'NoExplorer' = d '1'
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/tools/measure_page_load_time/ie_bho/MeasurePageLoadTime.vcproj b/tools/measure_page_load_time/ie_bho/MeasurePageLoadTime.vcproj
new file mode 100644
index 0000000..9ed8327
--- /dev/null
+++ b/tools/measure_page_load_time/ie_bho/MeasurePageLoadTime.vcproj
@@ -0,0 +1,320 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="MeasurePageLoadTime"
+ ProjectGUID="{151243DF-25BE-4A88-B566-8B7AE8970E86}"
+ RootNamespace="MeasurePageLoadTime"
+ Keyword="AtlProj"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="2"
+ UseOfATL="2"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ PreprocessorDefinitions="_DEBUG"
+ MkTypLibCompatible="false"
+ TargetEnvironment="1"
+ GenerateStublessProxies="true"
+ TypeLibraryName="$(IntDir)/MeasurePageLoadTime.tlb"
+ HeaderFileName="MeasurePageLoadTime.h"
+ DLLDataFileName=""
+ InterfaceIdentifierFileName="MeasurePageLoadTime_i.c"
+ ProxyFileName="MeasurePageLoadTime_p.c"
+ ValidateParameters="false"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions="WIN32;_WINDOWS;_DEBUG;_USRDLL"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ UsePrecompiledHeader="2"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="4"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="1033"
+ AdditionalIncludeDirectories="$(IntDir)"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ RegisterOutput="true"
+ IgnoreImportLibrary="true"
+ AdditionalDependencies="ws2_32.lib"
+ LinkIncremental="2"
+ ModuleDefinitionFile=".\MeasurePageLoadTime.def"
+ GenerateDebugInformation="true"
+ SubSystem="2"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="2"
+ UseOfATL="1"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ PreprocessorDefinitions="NDEBUG"
+ MkTypLibCompatible="false"
+ TargetEnvironment="1"
+ GenerateStublessProxies="true"
+ TypeLibraryName="$(IntDir)/MeasurePageLoadTime.tlb"
+ HeaderFileName="MeasurePageLoadTime.h"
+ DLLDataFileName=""
+ InterfaceIdentifierFileName="MeasurePageLoadTime_i.c"
+ ProxyFileName="MeasurePageLoadTime_p.c"
+ ValidateParameters="false"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ PreprocessorDefinitions="WIN32;_WINDOWS;NDEBUG;_USRDLL"
+ RuntimeLibrary="0"
+ UsePrecompiledHeader="2"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1033"
+ AdditionalIncludeDirectories="$(IntDir)"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ RegisterOutput="true"
+ IgnoreImportLibrary="true"
+ AdditionalDependencies="ws2_32.lib"
+ LinkIncremental="1"
+ ModuleDefinitionFile=".\MeasurePageLoadTime.def"
+ GenerateDebugInformation="true"
+ SubSystem="2"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+ >
+ <File
+ RelativePath=".\MeasurePageLoadTime.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\MeasurePageLoadTime.def"
+ >
+ </File>
+ <File
+ RelativePath=".\MeasurePageLoadTime.idl"
+ >
+ </File>
+ <File
+ RelativePath=".\MeasurePageLoadTimeBHO.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\stdafx.cpp"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="1"
+ />
+ </FileConfiguration>
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+ >
+ <File
+ RelativePath=".\MeasurePageLoadTimeBHO.h"
+ >
+ </File>
+ <File
+ RelativePath=".\stdafx.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
+ UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+ >
+ <File
+ RelativePath=".\MeasurePageLoadTime.rc"
+ >
+ </File>
+ <File
+ RelativePath=".\MeasurePageLoadTime.rgs"
+ >
+ </File>
+ <File
+ RelativePath=".\MeasurePageLoadTimeBHO.rgs"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Generated Files"
+ SourceControlFiles="false"
+ >
+ <File
+ RelativePath=".\MeasurePageLoadTime.h"
+ >
+ </File>
+ <File
+ RelativePath=".\MeasurePageLoadTime_i.c"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="0"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="0"
+ />
+ </FileConfiguration>
+ </File>
+ </Filter>
+ <File
+ RelativePath=".\ReadMe.txt"
+ >
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/tools/measure_page_load_time/ie_bho/MeasurePageLoadTimeBHO.cpp b/tools/measure_page_load_time/ie_bho/MeasurePageLoadTimeBHO.cpp
new file mode 100644
index 0000000..7e9d5c0
--- /dev/null
+++ b/tools/measure_page_load_time/ie_bho/MeasurePageLoadTimeBHO.cpp
@@ -0,0 +1,317 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Implements a Browser Helper Object (BHO) which opens a socket
+// and waits to receive URLs over it. Visits those URLs, measuring
+// how long it takes between the start of navigation and the
+// DocumentComplete event, and returns the time in milliseconds as
+// a string to the caller.
+
+#include "stdafx.h"
+#include "MeasurePageLoadTimeBHO.h"
+
+#define MAX_URL 1024 // size of URL buffer
+#define MAX_PAGELOADTIME (4*60*1000) // assume all pages take < 4 minutes
+#define PORT 42492 // port to listen on. Also jhaas's
+ // old MSFT employee number
+
+
+// Static function to serve as thread entry point, takes a "this"
+// pointer as pParam and calls the method in the object
+static DWORD WINAPI ProcessPageTimeRequests(LPVOID pThis) {
+ reinterpret_cast<CMeasurePageLoadTimeBHO*>(pThis)->ProcessPageTimeRequests();
+
+ return 0;
+}
+
+
+STDMETHODIMP CMeasurePageLoadTimeBHO::SetSite(IUnknown* pUnkSite)
+{
+ if (pUnkSite != NULL)
+ {
+ // Cache the pointer to IWebBrowser2.
+ HRESULT hr = pUnkSite->QueryInterface(IID_IWebBrowser2, (void **)&m_spWebBrowser);
+ if (SUCCEEDED(hr))
+ {
+ // Register to sink events from DWebBrowserEvents2.
+ hr = DispEventAdvise(m_spWebBrowser);
+ if (SUCCEEDED(hr))
+ {
+ m_fAdvised = TRUE;
+ }
+
+ // Stash the interface in the global interface table
+ CComGITPtr<IWebBrowser2> git(m_spWebBrowser);
+ m_dwCookie = git.Detach();
+
+ // Create the event to be signaled when navigation completes.
+ // Start it in nonsignaled state, and allow it to be triggered
+ // when the initial page load is done.
+ m_hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
+
+ // Create a thread to wait on the socket
+ HANDLE hThread = CreateThread(NULL, 0, ::ProcessPageTimeRequests, this, 0, NULL);
+ }
+ }
+ else
+ {
+ // Unregister event sink.
+ if (m_fAdvised)
+ {
+ DispEventUnadvise(m_spWebBrowser);
+ m_fAdvised = FALSE;
+ }
+
+ // Release cached pointers and other resources here.
+ m_spWebBrowser.Release();
+ }
+
+ // Call base class implementation.
+ return IObjectWithSiteImpl<CMeasurePageLoadTimeBHO>::SetSite(pUnkSite);
+}
+
+
+void STDMETHODCALLTYPE CMeasurePageLoadTimeBHO::OnDocumentComplete(IDispatch *pDisp, VARIANT *pvarURL)
+{
+ if (pDisp == m_spWebBrowser)
+ {
+ // Fire the event when the page is done loading
+ // to unblock the other thread.
+ SetEvent(m_hEvent);
+ }
+}
+
+
+void CMeasurePageLoadTimeBHO::ProcessPageTimeRequests()
+{
+ CoInitialize(NULL);
+
+ // The event will start in nonsignaled state, meaning that
+ // the initial page load isn't done yet. Wait for that to
+ // finish before doing anything.
+ //
+ // It seems to be the case that the BHO will get loaded
+ // and SetSite called always before the initial page load
+ // even begins, but just to be on the safe side, we won't
+ // wait indefinitely.
+ WaitForSingleObject(m_hEvent, MAX_PAGELOADTIME);
+
+ // Retrieve the web browser interface from the global table
+ CComGITPtr<IWebBrowser2> git(m_dwCookie);
+ IWebBrowser2* browser;
+ git.CopyTo(&browser);
+
+ // Create a listening socket
+ m_sockListen = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+ if (m_sockListen == SOCKET_ERROR)
+ ErrorExit();
+
+ BOOL on = TRUE;
+ if (setsockopt(m_sockListen, SOL_SOCKET, SO_REUSEADDR,
+ (const char*)&on, sizeof(on)))
+ ErrorExit();
+
+ // Bind the listening socket
+ SOCKADDR_IN addrBind;
+
+ addrBind.sin_family = AF_INET;
+ addrBind.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+ addrBind.sin_port = htons(PORT);
+
+ if (bind(m_sockListen, (sockaddr*)&addrBind, sizeof(addrBind)))
+ ErrorExit();
+
+ // Listen for incoming connections
+ if (listen(m_sockListen, 1))
+ ErrorExit();
+
+ // Ensure the socket is blocking... it should be by default, but
+ // it can't hurt to make sure
+ unsigned long nNonblocking = 0;
+ if (ioctlsocket(m_sockListen, FIONBIO, &nNonblocking))
+ ErrorExit();
+
+ m_sockTransport = 0;
+
+ // Loop indefinitely waiting for connections
+ while(1)
+ {
+ SOCKADDR_IN addrConnected;
+ int sConnected = sizeof(addrConnected);
+
+ // Wait for a client to connect and send a URL
+ m_sockTransport = accept(
+ m_sockListen, (sockaddr*)&addrConnected, &sConnected);
+
+ if (m_sockTransport == SOCKET_ERROR)
+ ErrorExit();
+
+ char pbBuffer[MAX_URL], strURL[MAX_URL];
+ DWORD cbRead, cbWritten;
+
+ bool fDone = false;
+
+ // Loop until we're done with this client
+ while (!fDone)
+ {
+ *strURL = '\0';
+ bool fReceivedCR = false;
+
+ do
+ {
+ // Only receive up to the first carriage return
+ cbRead = recv(m_sockTransport, pbBuffer, MAX_URL-1, MSG_PEEK);
+
+ // An error on read most likely means that the remote peer
+ // closed the connection. Go back to waiting
+ if (cbRead == 0)
+ {
+ fDone = true;
+ break;
+ }
+
+ // Null terminate the received characters so strchr() is safe
+ pbBuffer[cbRead] = '\0';
+
+ if(char* pchFirstCR = strchr(pbBuffer, '\n'))
+ {
+ cbRead = (DWORD)(pchFirstCR - pbBuffer + 1);
+ fReceivedCR = true;
+ }
+
+ // The below call will not block, since we determined with
+ // MSG_PEEK that at least cbRead bytes are in the TCP receive buffer
+ recv(m_sockTransport, pbBuffer, cbRead, 0);
+ pbBuffer[cbRead] = '\0';
+
+ strcat_s(strURL, sizeof(strURL), pbBuffer);
+ } while (!fReceivedCR);
+
+ // If an error occurred while reading, exit this loop
+ if (fDone)
+ break;
+
+ // Strip the trailing CR and/or LF
+ int i;
+ for (i = (int)strlen(strURL)-1; i >= 0 && isspace(strURL[i]); i--)
+ {
+ strURL[i] = '\0';
+ }
+
+ if (i < 0)
+ {
+ // Sending a carriage return on a line by itself means that
+ // the client is done making requests
+ fDone = true;
+ }
+ else
+ {
+ // Send the browser to the requested URL
+ CComVariant vNavFlags( navNoReadFromCache );
+ CComVariant vTargetFrame("_self");
+ CComVariant vPostData("");
+ CComVariant vHTTPHeaders("");
+
+ ResetEvent(m_hEvent);
+ DWORD dwStartTime = GetTickCount();
+
+ HRESULT hr = browser->Navigate(
+ CComBSTR(strURL),
+ &vNavFlags,
+ &vTargetFrame, // TargetFrameName
+ &vPostData, // PostData
+ &vHTTPHeaders // Headers
+ );
+
+ // The main browser thread will call OnDocumentComplete() when
+ // the page is done loading, which will in turn trigger
+ // m_hEvent. Wait here until then; the event will reset itself
+ // once this thread is released
+ if (WaitForSingleObject(m_hEvent, MAX_PAGELOADTIME) == WAIT_TIMEOUT)
+ {
+ sprintf_s(pbBuffer, sizeof(pbBuffer), "%s,timeout\n", strURL);
+
+ browser->Stop();
+ }
+ else
+ {
+ // Format the elapsed time as a string
+ DWORD dwLoadTime = GetTickCount() - dwStartTime;
+ sprintf_s(
+ pbBuffer, sizeof(pbBuffer), "%s,%d\n", strURL, dwLoadTime);
+ }
+
+ // Send the result. Just in case the TCP buffer can't handle
+ // the whole thing, send in parts if necessary
+ char *chSend = pbBuffer;
+
+ while (*chSend)
+ {
+ cbWritten = send(
+ m_sockTransport, chSend, (int)strlen(chSend), 0);
+
+ // Error on send probably means connection reset by peer
+ if (cbWritten == 0)
+ {
+ fDone = true;
+ break;
+ }
+
+ chSend += cbWritten;
+ }
+ }
+ }
+
+ // Close the transport socket and wait for another connection
+ closesocket(m_sockTransport);
+ m_sockTransport = 0;
+ }
+}
+
+
+void CMeasurePageLoadTimeBHO::ErrorExit()
+{
+ // Unlink from IE, close the sockets, then terminate this
+ // thread
+ SetSite(NULL);
+
+ if (m_sockTransport && m_sockTransport != SOCKET_ERROR)
+ {
+ closesocket(m_sockTransport);
+ m_sockTransport = 0;
+ }
+
+ if (m_sockListen && m_sockListen != SOCKET_ERROR)
+ {
+ closesocket(m_sockListen);
+ m_sockListen = 0;
+ }
+
+ TerminateThread(GetCurrentThread(), -1);
+} \ No newline at end of file
diff --git a/tools/measure_page_load_time/ie_bho/MeasurePageLoadTimeBHO.h b/tools/measure_page_load_time/ie_bho/MeasurePageLoadTimeBHO.h
new file mode 100644
index 0000000..fcfe04d
--- /dev/null
+++ b/tools/measure_page_load_time/ie_bho/MeasurePageLoadTimeBHO.h
@@ -0,0 +1,113 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// MeasurePageLoadTimeBHO.h : Declaration of the CMeasurePageLoadTimeBHO
+
+#pragma once
+#include "resource.h" // main symbols
+
+#include <shlguid.h> // IID_IWebBrowser2, DIID_DWebBrowserEvents2, et
+#include <exdispid.h> // DISPID_DOCUMENTCOMPLETE, etc.
+
+#include <string>
+
+#include "MeasurePageLoadTime.h"
+
+
+#if defined(_WIN32_WCE) && !defined(_CE_DCOM) && !defined(_CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA)
+#error "Single-threaded COM objects are not properly supported on Windows CE platform, such as the Windows Mobile platforms that do not include full DCOM support. Define _CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA to force ATL to support creating single-thread COM object's and allow use of it's single-threaded COM object implementations. The threading model in your rgs file was set to 'Free' as that is the only threading model supported in non DCOM Windows CE platforms."
+#endif
+
+
+
+// CMeasurePageLoadTimeBHO
+
+class ATL_NO_VTABLE CMeasurePageLoadTimeBHO :
+ public CComObjectRootEx<CComSingleThreadModel>,
+ public CComCoClass<CMeasurePageLoadTimeBHO, &CLSID_MeasurePageLoadTimeBHO>,
+ public IObjectWithSiteImpl<CMeasurePageLoadTimeBHO>,
+ public IDispatchImpl<IMeasurePageLoadTimeBHO, &IID_IMeasurePageLoadTimeBHO, &LIBID_MeasurePageLoadTimeLib, /*wMajor =*/ 1, /*wMinor =*/ 0>,
+ public IDispEventImpl<1, CMeasurePageLoadTimeBHO, &DIID_DWebBrowserEvents2, &LIBID_SHDocVw, 1, 1>
+{
+public:
+ CMeasurePageLoadTimeBHO()
+ {
+ }
+
+DECLARE_REGISTRY_RESOURCEID(IDR_MEASUREPAGELOADTIMEBHO)
+
+DECLARE_NOT_AGGREGATABLE(CMeasurePageLoadTimeBHO)
+
+BEGIN_COM_MAP(CMeasurePageLoadTimeBHO)
+ COM_INTERFACE_ENTRY(IMeasurePageLoadTimeBHO)
+ COM_INTERFACE_ENTRY(IDispatch)
+ COM_INTERFACE_ENTRY(IObjectWithSite)
+END_COM_MAP()
+
+BEGIN_SINK_MAP(CMeasurePageLoadTimeBHO)
+ SINK_ENTRY_EX(1, DIID_DWebBrowserEvents2, DISPID_DOCUMENTCOMPLETE, OnDocumentComplete)
+END_SINK_MAP()
+
+ // DWebBrowserEvents2
+ void STDMETHODCALLTYPE OnDocumentComplete(IDispatch *pDisp, VARIANT *pvarURL);
+ STDMETHOD(SetSite)(IUnknown *pUnkSite);
+
+ DECLARE_PROTECT_FINAL_CONSTRUCT()
+
+ HRESULT FinalConstruct()
+ {
+ return S_OK;
+ }
+
+ void FinalRelease()
+ {
+ }
+
+ void ProcessPageTimeRequests(void);
+ void VisitNextURL(void);
+ void ErrorExit(void);
+
+private:
+ CComPtr<IWebBrowser2> m_spWebBrowser;
+ BOOL m_fAdvised;
+
+ // Handle to global interface table
+ DWORD m_dwCookie;
+
+ // Handle to event to signal when navigation completes
+ HANDLE m_hEvent;
+
+ // Socket for accepting incoming connections
+ SOCKET m_sockListen;
+
+ // Socket for communicating with remote peers
+ SOCKET m_sockTransport;
+};
+
+OBJECT_ENTRY_AUTO(__uuidof(MeasurePageLoadTimeBHO), CMeasurePageLoadTimeBHO)
diff --git a/tools/measure_page_load_time/ie_bho/MeasurePageLoadTimeBHO.rgs b/tools/measure_page_load_time/ie_bho/MeasurePageLoadTimeBHO.rgs
new file mode 100644
index 0000000..907015f
--- /dev/null
+++ b/tools/measure_page_load_time/ie_bho/MeasurePageLoadTimeBHO.rgs
@@ -0,0 +1,27 @@
+HKCR
+{
+ MeasurePageLoadTime.MeasurePageLoadTi.1 = s 'MeasurePageLoadTimeBHO Class'
+ {
+ CLSID = s '{807E68BC-238F-4163-AE4B-0A3604F3E145}'
+ }
+ MeasurePageLoadTime.MeasurePageLoadTime = s 'MeasurePageLoadTimeBHO Class'
+ {
+ CLSID = s '{807E68BC-238F-4163-AE4B-0A3604F3E145}'
+ CurVer = s 'MeasurePageLoadTime.MeasurePageLoadTi.1'
+ }
+ NoRemove CLSID
+ {
+ ForceRemove {807E68BC-238F-4163-AE4B-0A3604F3E145} = s 'MeasurePageLoadTimeBHO Class'
+ {
+ ProgID = s 'MeasurePageLoadTime.MeasurePageLoadTi.1'
+ VersionIndependentProgID = s 'MeasurePageLoadTime.MeasurePageLoadTime'
+ ForceRemove 'Programmable'
+ InprocServer32 = s '%MODULE%'
+ {
+ val ThreadingModel = s 'Apartment'
+ }
+ val AppID = s '%APPID%'
+ 'TypeLib' = s '{61AC7AC4-B715-4955-A238-5F9AEA80DF4B}'
+ }
+ }
+}
diff --git a/tools/measure_page_load_time/ie_bho/resource.h b/tools/measure_page_load_time/ie_bho/resource.h
new file mode 100644
index 0000000..a8004dc
--- /dev/null
+++ b/tools/measure_page_load_time/ie_bho/resource.h
@@ -0,0 +1,18 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by MeasurePageLoadTime.rc
+//
+#define IDS_PROJNAME 100
+#define IDR_MEASUREPAGELOADTIME 101
+#define IDR_MEASUREPAGELOADTIMEBHO 102
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 201
+#define _APS_NEXT_COMMAND_VALUE 32768
+#define _APS_NEXT_CONTROL_VALUE 201
+#define _APS_NEXT_SYMED_VALUE 103
+#endif
+#endif
diff --git a/tools/measure_page_load_time/ie_bho/stdafx.cpp b/tools/measure_page_load_time/ie_bho/stdafx.cpp
new file mode 100644
index 0000000..c67b429
--- /dev/null
+++ b/tools/measure_page_load_time/ie_bho/stdafx.cpp
@@ -0,0 +1,5 @@
+// stdafx.cpp : source file that includes just the standard includes
+// MeasurePageLoadTime.pch will be the pre-compiled header
+// stdafx.obj will contain the pre-compiled type information
+
+#include "stdafx.h"
diff --git a/tools/measure_page_load_time/ie_bho/stdafx.h b/tools/measure_page_load_time/ie_bho/stdafx.h
new file mode 100644
index 0000000..3f26087
--- /dev/null
+++ b/tools/measure_page_load_time/ie_bho/stdafx.h
@@ -0,0 +1,39 @@
+// stdafx.h : include file for standard system include files,
+// or project specific include files that are used frequently,
+// but are changed infrequently
+
+#pragma once
+
+#ifndef STRICT
+#define STRICT
+#endif
+
+// Modify the following defines if you have to target a platform prior to the ones specified below.
+// Refer to MSDN for the latest info on corresponding values for different platforms.
+#ifndef WINVER // Allow use of features specific to Windows XP or later.
+#define WINVER 0x0501 // Change this to the appropriate value to target other versions of Windows.
+#endif
+
+#ifndef _WIN32_WINNT // Allow use of features specific to Windows XP or later.
+#define _WIN32_WINNT 0x0501 // Change this to the appropriate value to target other versions of Windows.
+#endif
+
+#ifndef _WIN32_WINDOWS // Allow use of features specific to Windows 98 or later.
+#define _WIN32_WINDOWS 0x0410 // Change this to the appropriate value to target Windows Me or later.
+#endif
+
+#ifndef _WIN32_IE // Allow use of features specific to IE 6.0 or later.
+#define _WIN32_IE 0x0600 // Change this to the appropriate value to target other versions of IE.
+#endif
+
+#define _ATL_APARTMENT_THREADED
+#define _ATL_NO_AUTOMATIC_NAMESPACE
+
+#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS // some CString constructors will be explicit
+
+
+#include "resource.h"
+#include <atlbase.h>
+#include <atlcom.h>
+
+using namespace ATL; \ No newline at end of file