1 # Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file.
5 """Utility to use a browser to visit multiple URLs.
8 1. The command_line package from tools/site_compare
9 2. Either the IE BHO or Firefox extension (or both)
12 1. Build the IE BHO, or call regsvr32 on a prebuilt binary
13 2. Add a file called "measurepageloadtimeextension@google.com" to
14 the default Firefox profile directory under extensions, containing
15 the path to the Firefox extension root
17 Invoke with the command line arguments as documented within
26 from drivers
import windowing
32 def SetupIterationCommandLine(cmd
):
33 """Adds the necessary flags for iteration to a command.
36 cmd: an object created by cmdline.AddCommand
39 ["-b", "--browser"], "Browser to use (ie, firefox, chrome)",
40 type="string", required
=True)
42 ["-b1v", "--browserver"], "Version of browser", metaname
="VERSION")
44 ["-p", "--browserpath"], "Path to browser.",
45 type="string", required
=False)
47 ["-u", "--url"], "URL to visit")
49 ["-l", "--list"], "File containing list of URLs to visit", type="readfile")
50 cmd
.AddMutualExclusion(["--url", "--list"])
52 ["-s", "--startline"], "First line of URL list", type="int")
54 ["-e", "--endline"], "Last line of URL list (exclusive)", type="int")
56 ["-c", "--count"], "Number of lines of URL file to use", type="int")
57 cmd
.AddDependency("--startline", "--list")
58 cmd
.AddRequiredGroup(["--url", "--list"])
59 cmd
.AddDependency("--endline", "--list")
60 cmd
.AddDependency("--count", "--list")
61 cmd
.AddMutualExclusion(["--count", "--endline"])
62 cmd
.AddDependency("--count", "--startline")
64 ["-t", "--timeout"], "Amount of time (seconds) to wait for browser to "
66 type="int", default
=300)
68 ["-sz", "--size"], "Browser window size", default
=(800, 600), type="coords")
71 def Iterate(command
, iteration_func
):
72 """Iterates over a list of URLs, calling a function on each.
75 command: the command line containing the iteration flags
76 iteration_func: called for each URL with (proc, wnd, url, result)
79 # Retrieve the browser scraper to use to invoke the browser
80 scraper
= scrapers
.GetScraper((command
["--browser"], command
["--browserver"]))
82 def AttachToBrowser(path
, timeout
):
83 """Invoke the browser process and connect to the socket."""
84 (proc
, frame
, wnd
) = scraper
.GetBrowser(path
)
86 if not wnd
: raise ValueError("Could not invoke browser.")
88 # Try to connect the socket. If it fails, wait and try
89 # again. Do this for ten seconds
90 s
= socket
.socket(socket
.AF_INET
, socket
.SOCK_STREAM
, socket
.IPPROTO_TCP
)
92 for attempt
in xrange(10):
94 s
.connect(("localhost", PORT
))
103 raise ValueError("Could not connect to browser")
105 if command
["--size"]:
106 # Resize and reposition the frame
107 windowing
.MoveAndSizeWindow(frame
, (0, 0), command
["--size"], wnd
)
109 s
.settimeout(timeout
)
115 def DetachFromBrowser():
116 """Close the socket and kill the process if necessary."""
122 if not windowing
.WaitForProcessExit(Iterate
.proc
, 0):
124 windowing
.EndProcess(Iterate
.proc
)
125 windowing
.WaitForProcessExit(Iterate
.proc
, 0)
126 except pywintypes
.error
:
127 # Exception here most likely means the process died on its own
131 if command
["--browserpath"]:
132 browser
= command
["--browserpath"]
136 # Read the URLs from the file
138 url_list
= [command
["--url"]]
140 startline
= command
["--startline"]
141 if command
["--count"]:
142 endline
= startline
+command
["--count"]
144 endline
= command
["--endline"]
147 file = open(command
["--list"], "r")
149 for line
in xrange(startline
-1):
152 for line
in xrange(endline
-startline
):
153 url_list
.append(file.readline().strip())
155 timeout
= command
["--timeout"]
157 # Loop through the URLs and send them through the socket
163 # Invoke the browser if necessary
165 AttachToBrowser(browser
, timeout
)
166 # Send the URL and wait for a response
167 Iterate
.s
.send(url
+ "\n")
171 while (response
.find("\n") < 0):
174 recv
= Iterate
.s
.recv(MAX_URL
)
175 response
= response
+ recv
177 # Workaround for an oddity: when Firefox closes
178 # gracefully, somehow Python doesn't detect it.
183 except socket
.timeout
:
184 response
= url
+ ",hang\n"
187 # If there was a socket error, it's probably a crash
188 response
= url
+ ",crash\n"
191 # If we received a timeout response, restart the browser
192 if response
[-9:] == ",timeout\n":
195 # Invoke the iteration function
196 iteration_func(url
, Iterate
.proc
, Iterate
.wnd
, response
)