summaryrefslogtreecommitdiffstats
path: root/chrome/test
diff options
context:
space:
mode:
Diffstat (limited to 'chrome/test')
-rw-r--r--chrome/test/accessibility/accessibility_tests.cc503
-rw-r--r--chrome/test/accessibility/accessibility_util.cc620
-rw-r--r--chrome/test/accessibility/accessibility_util.h136
-rw-r--r--chrome/test/accessibility/browser_impl.cc551
-rw-r--r--chrome/test/accessibility/browser_impl.h134
-rw-r--r--chrome/test/accessibility/constants.h134
-rw-r--r--chrome/test/accessibility/keyboard_util.cc219
-rw-r--r--chrome/test/accessibility/keyboard_util.h62
-rw-r--r--chrome/test/accessibility/registry_util.cc37
-rw-r--r--chrome/test/accessibility/registry_util.h42
-rw-r--r--chrome/test/accessibility/tab_impl.cc389
-rw-r--r--chrome/test/accessibility/tab_impl.h163
-rw-r--r--chrome/test/activex_test_control/SConscript93
-rw-r--r--chrome/test/activex_test_control/activex_test_control.cc74
-rw-r--r--chrome/test/activex_test_control/activex_test_control.def9
-rw-r--r--chrome/test/activex_test_control/activex_test_control.idl108
-rw-r--r--chrome/test/activex_test_control/activex_test_control.rc128
-rw-r--r--chrome/test/activex_test_control/activex_test_control.rgs11
-rw-r--r--chrome/test/activex_test_control/activex_test_control.vcproj193
-rw-r--r--chrome/test/activex_test_control/activex_test_control.vsprops26
-rw-r--r--chrome/test/activex_test_control/chrome_test_control.bmpbin0 -> 246 bytes
-rw-r--r--chrome/test/activex_test_control/chrome_test_control.cc59
-rw-r--r--chrome/test/activex_test_control/chrome_test_control.h286
-rw-r--r--chrome/test/activex_test_control/chrome_test_control.rgs34
-rw-r--r--chrome/test/activex_test_control/chrome_test_control_cp.h42
-rw-r--r--chrome/test/activex_test_control/resource.h19
-rw-r--r--chrome/test/automated_ui_tests/automated_ui_tests.cc887
-rw-r--r--chrome/test/automated_ui_tests/automated_ui_tests.h443
-rw-r--r--chrome/test/automated_ui_tests/automated_ui_tests.vcproj212
-rw-r--r--chrome/test/automation/SConscript58
-rw-r--r--chrome/test/automation/autocomplete_edit_proxy.cc136
-rw-r--r--chrome/test/automation/autocomplete_edit_proxy.h169
-rw-r--r--chrome/test/automation/automation.vcproj193
-rw-r--r--chrome/test/automation/automation.vsprops11
-rw-r--r--chrome/test/automation/automation_constants.h38
-rw-r--r--chrome/test/automation/automation_handle_tracker.cc97
-rw-r--r--chrome/test/automation/automation_handle_tracker.h128
-rw-r--r--chrome/test/automation/automation_messages.h65
-rw-r--r--chrome/test/automation/automation_messages_internal.h723
-rw-r--r--chrome/test/automation/automation_proxy.cc567
-rw-r--r--chrome/test/automation/automation_proxy.h240
-rw-r--r--chrome/test/automation/automation_proxy_uitest.cc831
-rw-r--r--chrome/test/automation/browser_proxy.cc348
-rw-r--r--chrome/test/automation/browser_proxy.h164
-rw-r--r--chrome/test/automation/constrained_window_proxy.cc92
-rw-r--r--chrome/test/automation/constrained_window_proxy.h59
-rw-r--r--chrome/test/automation/tab_proxy.cc920
-rw-r--r--chrome/test/automation/tab_proxy.h266
-rw-r--r--chrome/test/automation/ui_controls.cc0
-rw-r--r--chrome/test/automation/ui_controls.h0
-rw-r--r--chrome/test/automation/window_proxy.cc187
-rw-r--r--chrome/test/automation/window_proxy.h106
-rw-r--r--chrome/test/chrome_plugin/SConscript98
-rw-r--r--chrome/test/chrome_plugin/test_chrome_plugin.cc401
-rw-r--r--chrome/test/chrome_plugin/test_chrome_plugin.def4
-rw-r--r--chrome/test/chrome_plugin/test_chrome_plugin.h92
-rw-r--r--chrome/test/chrome_plugin/test_chrome_plugin.vcproj159
-rw-r--r--chrome/test/chrome_plugin/test_chrome_plugin.vsprops13
-rw-r--r--chrome/test/data/animate1.gifbin0 -> 19021 bytes
-rw-r--r--chrome/test/data/animate2.gifbin0 -> 10906 bytes
-rw-r--r--chrome/test/data/animate3.gifbin0 -> 1769 bytes
-rw-r--r--chrome/test/data/animated-gifs.html8
-rw-r--r--chrome/test/data/cancelled_redirect_test.html28
-rw-r--r--chrome/test/data/columns.html23
-rw-r--r--chrome/test/data/constrained_files/constrained_window.html17
-rw-r--r--chrome/test/data/constrained_files/constrained_window_onload_moveto.html17
-rw-r--r--chrome/test/data/constrained_files/constrained_window_onload_resizeto.html17
-rw-r--r--chrome/test/data/constrained_files/target0.html8
-rw-r--r--chrome/test/data/constrained_files/target1.html6
-rw-r--r--chrome/test/data/constrained_files/target_onload_moveto.html8
-rw-r--r--chrome/test/data/constrained_files/target_onload_resizeto.html9
-rw-r--r--chrome/test/data/content-disposition-empty.html4
-rw-r--r--chrome/test/data/content-disposition-empty.html.mock-http-headers6
-rw-r--r--chrome/test/data/content-disposition-inline.html4
-rw-r--r--chrome/test/data/content-disposition-inline.html.mock-http-headers6
-rw-r--r--chrome/test/data/content-sniffer-test0.html4
-rw-r--r--chrome/test/data/content-sniffer-test0.html.mock-http-headers4
-rw-r--r--chrome/test/data/content-sniffer-test1.html4
-rw-r--r--chrome/test/data/content-sniffer-test1.html.mock-http-headers5
-rw-r--r--chrome/test/data/content-sniffer-test2.html4
-rw-r--r--chrome/test/data/content-sniffer-test2.html.mock-http-headers5
-rw-r--r--chrome/test/data/content-sniffer-test3-frame.txt0
-rw-r--r--chrome/test/data/content-sniffer-test3-frame.txt.mock-http-headers3
-rw-r--r--chrome/test/data/content-sniffer-test3.html16
-rw-r--r--chrome/test/data/content-sniffer-test3.html.mock-http-headers5
-rw-r--r--chrome/test/data/cookie1.html11
-rw-r--r--chrome/test/data/download-test1.libbin0 -> 271920 bytes
-rw-r--r--chrome/test/data/download-test1.lib.mock-http-headers5
-rw-r--r--chrome/test/data/download-test2.html4
-rw-r--r--chrome/test/data/download-test2.html.mock-http-headers5
-rw-r--r--chrome/test/data/download-test3.html0
-rw-r--r--chrome/test/data/download-test3.html.mock-http-headers6
-rw-r--r--chrome/test/data/empty.html0
-rw-r--r--chrome/test/data/file_client_redirect.html8
-rw-r--r--chrome/test/data/find_in_page/framedata_general.html13
-rw-r--r--chrome/test/data/find_in_page/framedata_left.html21
-rw-r--r--chrome/test/data/find_in_page/frames.html12
-rw-r--r--chrome/test/data/find_in_page/user-select.html6
-rw-r--r--chrome/test/data/firefox2_nss/README7
-rw-r--r--chrome/test/data/firefox2_nss/freebl3.dllbin0 -> 200829 bytes
-rw-r--r--chrome/test/data/firefox2_nss/nspr4.dllbin0 -> 161392 bytes
-rw-r--r--chrome/test/data/firefox2_nss/nss3.dllbin0 -> 378472 bytes
-rw-r--r--chrome/test/data/firefox2_nss/plc4.dllbin0 -> 34424 bytes
-rw-r--r--chrome/test/data/firefox2_nss/plds4.dllbin0 -> 30320 bytes
-rw-r--r--chrome/test/data/firefox2_nss/softokn3.dllbin0 -> 254060 bytes
-rw-r--r--chrome/test/data/firefox2_profile/bookmarks.html37
-rw-r--r--chrome/test/data/firefox2_profile/cert8.dbbin0 -> 65536 bytes
-rw-r--r--chrome/test/data/firefox2_profile/cookies.txt10
-rw-r--r--chrome/test/data/firefox2_profile/history.dat16
-rw-r--r--chrome/test/data/firefox2_profile/key3.dbbin0 -> 16384 bytes
-rw-r--r--chrome/test/data/firefox2_profile/prefs.js209
-rw-r--r--chrome/test/data/firefox2_profile/signons2.txt29
-rw-r--r--chrome/test/data/firefox3_nss/README13
-rw-r--r--chrome/test/data/firefox3_nss/freebl3.dllbin0 -> 233472 bytes
-rw-r--r--chrome/test/data/firefox3_nss/mozcrt19.dllbin0 -> 710144 bytes
-rw-r--r--chrome/test/data/firefox3_nss/nspr4.dllbin0 -> 198144 bytes
-rw-r--r--chrome/test/data/firefox3_nss/nss3.dllbin0 -> 697856 bytes
-rw-r--r--chrome/test/data/firefox3_nss/nssdbm3.dllbin0 -> 103936 bytes
-rw-r--r--chrome/test/data/firefox3_nss/nssutil3.dllbin0 -> 87552 bytes
-rw-r--r--chrome/test/data/firefox3_nss/plc4.dllbin0 -> 20480 bytes
-rw-r--r--chrome/test/data/firefox3_nss/plds4.dllbin0 -> 17408 bytes
-rw-r--r--chrome/test/data/firefox3_nss/softokn3.dllbin0 -> 151552 bytes
-rw-r--r--chrome/test/data/firefox3_nss/sqlite3.dllbin0 -> 414208 bytes
-rw-r--r--chrome/test/data/firefox3_profile/cert8.dbbin0 -> 65536 bytes
-rw-r--r--chrome/test/data/firefox3_profile/cookies.sqlitebin0 -> 2048 bytes
-rw-r--r--chrome/test/data/firefox3_profile/key3.dbbin0 -> 16384 bytes
-rw-r--r--chrome/test/data/firefox3_profile/places.sqlitebin0 -> 131072 bytes
-rw-r--r--chrome/test/data/firefox3_profile/prefs.js32
-rw-r--r--chrome/test/data/firefox3_profile/search.sqlitebin0 -> 2048 bytes
-rw-r--r--chrome/test/data/firefox3_profile/secmod.dbbin0 -> 16384 bytes
-rw-r--r--chrome/test/data/firefox3_profile/signons3.txt18
-rw-r--r--chrome/test/data/focus/page_steals_focus.html55
-rw-r--r--chrome/test/data/focus/page_with_focus.html24
-rw-r--r--chrome/test/data/focus/typical_page.html47
-rw-r--r--chrome/test/data/frame_dom_access/frame_dom_access.html6
-rw-r--r--chrome/test/data/frame_dom_access/frame_level_1.html6
-rw-r--r--chrome/test/data/frame_dom_access/frame_level_2.html5
-rw-r--r--chrome/test/data/google/google.html17
-rw-r--r--chrome/test/data/google/logo.gifbin0 -> 8558 bytes
-rw-r--r--chrome/test/data/google/x2.gifbin0 -> 83 bytes
-rw-r--r--chrome/test/data/http_to_file.html5
-rw-r--r--chrome/test/data/icon_util/128_X_128_icon.icobin0 -> 67646 bytes
-rw-r--r--chrome/test/data/icon_util/16_X_16_icon.icobin0 -> 1150 bytes
-rw-r--r--chrome/test/data/ie@cookie[1].txt69
-rw-r--r--chrome/test/data/iframe.html4
-rw-r--r--chrome/test/data/iframe_in_empty_frame.html18
-rw-r--r--chrome/test/data/iframe_in_empty_frame.js3
-rw-r--r--chrome/test/data/inspector/dummy.js3
-rw-r--r--chrome/test/data/inspector/test1.html4
-rw-r--r--chrome/test/data/inspector/test2.html5
-rw-r--r--chrome/test/data/interstitial_page/google.html17
-rw-r--r--chrome/test/data/interstitial_page/interstitial.html7
-rw-r--r--chrome/test/data/interstitial_page/logo.gifbin0 -> 8558 bytes
-rw-r--r--chrome/test/data/interstitial_page/shopping.html123
-rw-r--r--chrome/test/data/interstitial_page/shopping_files/froogle.css1
-rw-r--r--chrome/test/data/interstitial_page/shopping_files/hp0.gifbin0 -> 4277 bytes
-rw-r--r--chrome/test/data/interstitial_page/shopping_files/hp1.gifbin0 -> 2953 bytes
-rw-r--r--chrome/test/data/interstitial_page/shopping_files/hp2.gifbin0 -> 2702 bytes
-rw-r--r--chrome/test/data/interstitial_page/shopping_files/hp3.gifbin0 -> 1410 bytes
-rw-r--r--chrome/test/data/interstitial_page/x2.gifbin0 -> 83 bytes
-rw-r--r--chrome/test/data/npapi/arguments.html40
-rw-r--r--chrome/test/data/npapi/execute_script_delete_in_npn_evaluate.html39
-rw-r--r--chrome/test/data/npapi/execute_script_delete_in_paint.html39
-rw-r--r--chrome/test/data/npapi/get_javascript_url.html26
-rw-r--r--chrome/test/data/npapi/geturl.html26
-rw-r--r--chrome/test/data/npapi/layout_test_plugin.html17
-rw-r--r--chrome/test/data/npapi/many_plugins.html94
-rw-r--r--chrome/test/data/npapi/new_fails.html30
-rw-r--r--chrome/test/data/npapi/npapi.js28
-rw-r--r--chrome/test/data/npapi/npobject_lifetime_test.html58
-rw-r--r--chrome/test/data/npapi/npobject_lifetime_test_second_instance.html20
-rw-r--r--chrome/test/data/npapi/npobject_proxy.html28
-rw-r--r--chrome/test/data/npapi/self_delete_plugin_geturl.html37
-rw-r--r--chrome/test/data/npapi/self_delete_plugin_invoke.html33
-rw-r--r--chrome/test/data/npapi/self_delete_plugin_stream.html34
-rw-r--r--chrome/test/data/npapi/verify_plugin_window_rect.html30
-rw-r--r--chrome/test/data/omnibox_tests.xml38
-rw-r--r--chrome/test/data/onunload_cookie.html18
-rw-r--r--chrome/test/data/pref_service/overlay.json22
-rw-r--r--chrome/test/data/pref_service/read.json7
-rw-r--r--chrome/test/data/pref_service/write.golden.json7
-rw-r--r--chrome/test/data/printing/alert_small.pngbin0 -> 764 bytes
-rw-r--r--chrome/test/data/printing/cleardot.gifbin0 -> 43 bytes
-rw-r--r--chrome/test/data/printing/click_me.pngbin0 -> 787 bytes
-rw-r--r--chrome/test/data/printing/iframe.emfbin0 -> 54656 bytes
-rw-r--r--chrome/test/data/printing/iframe.htm29
-rw-r--r--chrome/test/data/printing/iframe.pngbin0 -> 4003 bytes
-rw-r--r--chrome/test/data/printing/popup_delayed_print.emfbin0 -> 41108 bytes
-rw-r--r--chrome/test/data/printing/popup_delayed_print.htm13
-rw-r--r--chrome/test/data/printing/popup_delayed_print.pngbin0 -> 5644 bytes
-rw-r--r--chrome/test/data/printing/popup_delayed_print_child.htm14
-rw-r--r--chrome/test/data/printing/sadtab.pngbin0 -> 422 bytes
-rw-r--r--chrome/test/data/printing/test1.emfbin0 -> 4276 bytes
-rw-r--r--chrome/test/data/printing/test1.html20
-rw-r--r--chrome/test/data/printing/test1.pngbin0 -> 6482 bytes
-rw-r--r--chrome/test/data/printing/test1_cleartype.pngbin0 -> 10735 bytes
-rw-r--r--chrome/test/data/printing/test2.emfbin0 -> 54656 bytes
-rw-r--r--chrome/test/data/printing/test2.html10
-rw-r--r--chrome/test/data/printing/test2.pngbin0 -> 4003 bytes
-rw-r--r--chrome/test/data/printing/test3.emfbin0 -> 1860 bytes
-rw-r--r--chrome/test/data/printing/test3.html8
-rw-r--r--chrome/test/data/printing/test3.pngbin0 -> 3535 bytes
-rw-r--r--chrome/test/data/printing/test4.emfbin0 -> 6488 bytes
-rw-r--r--chrome/test/data/printing/test4.html10
-rw-r--r--chrome/test/data/printing/test4.pngbin0 -> 5558 bytes
-rw-r--r--chrome/test/data/printing/test5.emfbin0 -> 18532 bytes
-rw-r--r--chrome/test/data/printing/test5.html18
-rw-r--r--chrome/test/data/printing/test5.pngbin0 -> 3752 bytes
-rw-r--r--chrome/test/data/profiles/chrome_prefs/History0
-rw-r--r--chrome/test/data/profiles/chrome_prefs/Preferences15
-rw-r--r--chrome/test/data/profiles/sample/Full Text Indexbin0 -> 78848 bytes
-rw-r--r--chrome/test/data/profiles/sample/Historybin0 -> 19456 bytes
-rw-r--r--chrome/test/data/profiles/sample/Preferences1
-rw-r--r--chrome/test/data/profiles/sample/Thumbnailsbin0 -> 102400 bytes
-rw-r--r--chrome/test/data/profiles/sample/Visited Linksbin0 -> 131072 bytes
-rw-r--r--chrome/test/data/profiles/sample/Web Databin0 -> 40960 bytes
-rw-r--r--chrome/test/data/profiles/typical_history/Default/Cookiesbin0 -> 6144 bytes
-rw-r--r--chrome/test/data/profiles/typical_history/Default/Full Text Indexbin0 -> 20480 bytes
-rw-r--r--chrome/test/data/profiles/typical_history/Default/Historybin0 -> 14778368 bytes
-rw-r--r--chrome/test/data/profiles/typical_history/Default/Preferences11
-rw-r--r--chrome/test/data/profiles/typical_history/Default/Thumbnailsbin0 -> 32768 bytes
-rw-r--r--chrome/test/data/profiles/typical_history/Default/Visited Linksbin0 -> 131072 bytes
-rw-r--r--chrome/test/data/profiles/typical_history/README.txt14
-rw-r--r--chrome/test/data/profiles/window_placement/Local State11
-rw-r--r--chrome/test/data/purify/ignore.txt6
-rw-r--r--chrome/test/data/purify/ipc_tests.exe_MLK.txt0
-rw-r--r--chrome/test/data/purify/ipc_tests.exe_UMR.txt157
-rw-r--r--chrome/test/data/purify/unit_tests.exe.gtest.txt2
-rw-r--r--chrome/test/data/purify/unit_tests.exe_FIM.txt0
-rw-r--r--chrome/test/data/purify/unit_tests.exe_FIM_flakey.txt12
-rw-r--r--chrome/test/data/purify/unit_tests.exe_IPR.txt0
-rw-r--r--chrome/test/data/purify/unit_tests.exe_MLK.txt0
-rw-r--r--chrome/test/data/purify/unit_tests.exe_MLK_flakey.txt97
-rw-r--r--chrome/test/data/purify/unit_tests.exe_UMR.txt0
-rw-r--r--chrome/test/data/purify/unit_tests.exe_UMR_flakey.txt100
-rw-r--r--chrome/test/data/read_cookies.html35
-rw-r--r--chrome/test/data/ref_redirect.html8
-rw-r--r--chrome/test/data/resource.h23
-rw-r--r--chrome/test/data/resource.rc80
-rw-r--r--chrome/test/data/safe_browsing/download_update.py33
-rw-r--r--chrome/test/data/safe_browsing/initial/000goog-malware-shavar_sbin0 -> 97375 bytes
-rw-r--r--chrome/test/data/safe_browsing/initial/001goog-malware-shavar_sbin0 -> 127598 bytes
-rw-r--r--chrome/test/data/safe_browsing/initial/002goog-malware-shavar_sbin0 -> 143562 bytes
-rw-r--r--chrome/test/data/safe_browsing/initial/003goog-malware-shavar_sbin0 -> 123490 bytes
-rw-r--r--chrome/test/data/safe_browsing/initial/004goog-malware-shavar_sbin0 -> 152038 bytes
-rw-r--r--chrome/test/data/safe_browsing/initial/005goog-malware-shavar_sbin0 -> 167281 bytes
-rw-r--r--chrome/test/data/safe_browsing/initial/006goog-malware-shavar_sbin0 -> 168447 bytes
-rw-r--r--chrome/test/data/safe_browsing/initial/007goog-malware-shavar_sbin0 -> 171361 bytes
-rw-r--r--chrome/test/data/safe_browsing/initial/008goog-malware-shavar_sbin0 -> 155878 bytes
-rw-r--r--chrome/test/data/safe_browsing/initial/009goog-malware-shavar_sbin0 -> 169394 bytes
-rw-r--r--chrome/test/data/safe_browsing/initial/010goog-malware-shavar_abin0 -> 198030 bytes
-rw-r--r--chrome/test/data/safe_browsing/initial/011goog-malware-shavar_abin0 -> 72219 bytes
-rw-r--r--chrome/test/data/safe_browsing/initial/012goog-malware-shavar_abin0 -> 115525 bytes
-rw-r--r--chrome/test/data/safe_browsing/initial/013goog-malware-shavar_abin0 -> 178066 bytes
-rw-r--r--chrome/test/data/safe_browsing/initial/014goog-malware-shavar_abin0 -> 57907 bytes
-rw-r--r--chrome/test/data/safe_browsing/initial/015goog-phish-shavar_sbin0 -> 273 bytes
-rw-r--r--chrome/test/data/safe_browsing/initial/016goog-phish-shavar_sbin0 -> 269 bytes
-rw-r--r--chrome/test/data/safe_browsing/initial/017goog-phish-shavar_sbin0 -> 255 bytes
-rw-r--r--chrome/test/data/safe_browsing/initial/018goog-phish-shavar_sbin0 -> 442 bytes
-rw-r--r--chrome/test/data/safe_browsing/initial/019goog-phish-shavar_sbin0 -> 347 bytes
-rw-r--r--chrome/test/data/safe_browsing/initial/020goog-phish-shavar_sbin0 -> 887 bytes
-rw-r--r--chrome/test/data/safe_browsing/initial/021goog-phish-shavar_sbin0 -> 196 bytes
-rw-r--r--chrome/test/data/safe_browsing/initial/022goog-phish-shavar_sbin0 -> 395 bytes
-rw-r--r--chrome/test/data/safe_browsing/initial/023goog-phish-shavar_sbin0 -> 260 bytes
-rw-r--r--chrome/test/data/safe_browsing/initial/024goog-phish-shavar_sbin0 -> 260 bytes
-rw-r--r--chrome/test/data/safe_browsing/initial/025goog-phish-shavar_sbin0 -> 388 bytes
-rw-r--r--chrome/test/data/safe_browsing/initial/026goog-phish-shavar_sbin0 -> 461 bytes
-rw-r--r--chrome/test/data/safe_browsing/initial/027goog-phish-shavar_sbin0 -> 423 bytes
-rw-r--r--chrome/test/data/safe_browsing/initial/028goog-phish-shavar_sbin0 -> 186 bytes
-rw-r--r--chrome/test/data/safe_browsing/initial/029goog-phish-shavar_sbin0 -> 282 bytes
-rw-r--r--chrome/test/data/safe_browsing/initial/030goog-phish-shavar_sbin0 -> 182 bytes
-rw-r--r--chrome/test/data/safe_browsing/initial/031goog-phish-shavar_sbin0 -> 625 bytes
-rw-r--r--chrome/test/data/safe_browsing/initial/032goog-phish-shavar_sbin0 -> 269 bytes
-rw-r--r--chrome/test/data/safe_browsing/initial/033goog-phish-shavar_sbin0 -> 243 bytes
-rw-r--r--chrome/test/data/safe_browsing/initial/034goog-phish-shavar_sbin0 -> 381 bytes
-rw-r--r--chrome/test/data/safe_browsing/initial/035goog-phish-shavar_sbin0 -> 361 bytes
-rw-r--r--chrome/test/data/safe_browsing/initial/036goog-phish-shavar_sbin0 -> 289 bytes
-rw-r--r--chrome/test/data/safe_browsing/initial/037goog-phish-shavar_sbin0 -> 292 bytes
-rw-r--r--chrome/test/data/safe_browsing/initial/038goog-phish-shavar_sbin0 -> 306 bytes
-rw-r--r--chrome/test/data/safe_browsing/initial/039goog-phish-shavar_sbin0 -> 271 bytes
-rw-r--r--chrome/test/data/safe_browsing/initial/040goog-phish-shavar_sbin0 -> 655 bytes
-rw-r--r--chrome/test/data/safe_browsing/initial/041goog-phish-shavar_sbin0 -> 494 bytes
-rw-r--r--chrome/test/data/safe_browsing/initial/042goog-phish-shavar_sbin0 -> 2084 bytes
-rw-r--r--chrome/test/data/safe_browsing/initial/043goog-phish-shavar_sbin0 -> 328 bytes
-rw-r--r--chrome/test/data/safe_browsing/initial/044goog-phish-shavar_sbin0 -> 1973 bytes
-rw-r--r--chrome/test/data/safe_browsing/initial/045goog-phish-shavar_sbin0 -> 2809 bytes
-rw-r--r--chrome/test/data/safe_browsing/initial/046goog-phish-shavar_sbin0 -> 15562 bytes
-rw-r--r--chrome/test/data/safe_browsing/initial/047goog-phish-shavar_sbin0 -> 6933 bytes
-rw-r--r--chrome/test/data/safe_browsing/initial/048goog-phish-shavar_abin0 -> 7385 bytes
-rw-r--r--chrome/test/data/safe_browsing/initial/049goog-phish-shavar_abin0 -> 14177 bytes
-rw-r--r--chrome/test/data/safe_browsing/initial/050goog-phish-shavar_abin0 -> 17844 bytes
-rw-r--r--chrome/test/data/safe_browsing/initial/051goog-phish-shavar_abin0 -> 12683 bytes
-rw-r--r--chrome/test/data/safe_browsing/initial/052goog-phish-shavar_abin0 -> 1026 bytes
-rw-r--r--chrome/test/data/safe_browsing/old/SafeBrowsingbin0 -> 53770240 bytes
-rw-r--r--chrome/test/data/safe_browsing/old/postdata2
-rw-r--r--chrome/test/data/safe_browsing/old/response48
-rw-r--r--chrome/test/data/safe_browsing/old/updates/000goog-malware-shavar_sbin0 -> 168447 bytes
-rw-r--r--chrome/test/data/safe_browsing/old/updates/001goog-malware-shavar_sbin0 -> 171361 bytes
-rw-r--r--chrome/test/data/safe_browsing/old/updates/002goog-malware-shavar_sbin0 -> 155878 bytes
-rw-r--r--chrome/test/data/safe_browsing/old/updates/003goog-malware-shavar_sbin0 -> 169394 bytes
-rw-r--r--chrome/test/data/safe_browsing/old/updates/004goog-malware-shavar_sbin0 -> 169488 bytes
-rw-r--r--chrome/test/data/safe_browsing/old/updates/005goog-malware-shavar_sbin0 -> 120198 bytes
-rw-r--r--chrome/test/data/safe_browsing/old/updates/006goog-malware-shavar_sbin0 -> 167736 bytes
-rw-r--r--chrome/test/data/safe_browsing/old/updates/007goog-malware-shavar_sbin0 -> 71568 bytes
-rw-r--r--chrome/test/data/safe_browsing/old/updates/008goog-malware-shavar_abin0 -> 177464 bytes
-rw-r--r--chrome/test/data/safe_browsing/old/updates/009goog-malware-shavar_abin0 -> 127616 bytes
-rw-r--r--chrome/test/data/safe_browsing/old/updates/010goog-malware-shavar_abin0 -> 33211 bytes
-rw-r--r--chrome/test/data/safe_browsing/old/updates/011goog-phish-shavar_sbin0 -> 12998 bytes
-rw-r--r--chrome/test/data/safe_browsing/old/updates/012goog-phish-shavar_sbin0 -> 13506 bytes
-rw-r--r--chrome/test/data/safe_browsing/old/updates/013goog-phish-shavar_sbin0 -> 14079 bytes
-rw-r--r--chrome/test/data/safe_browsing/old/updates/014goog-phish-shavar_sbin0 -> 19250 bytes
-rw-r--r--chrome/test/data/safe_browsing/old/updates/015goog-phish-shavar_sbin0 -> 12842 bytes
-rw-r--r--chrome/test/data/safe_browsing/old/updates/016goog-phish-shavar_sbin0 -> 11214 bytes
-rw-r--r--chrome/test/data/safe_browsing/old/updates/017goog-phish-shavar_sbin0 -> 13766 bytes
-rw-r--r--chrome/test/data/safe_browsing/old/updates/018goog-phish-shavar_sbin0 -> 15249 bytes
-rw-r--r--chrome/test/data/safe_browsing/old/updates/019goog-phish-shavar_sbin0 -> 587 bytes
-rw-r--r--chrome/test/data/safe_browsing/old/updates/020goog-phish-shavar_sbin0 -> 482 bytes
-rw-r--r--chrome/test/data/safe_browsing/old/updates/021goog-phish-shavar_sbin0 -> 418 bytes
-rw-r--r--chrome/test/data/safe_browsing/old/updates/022goog-phish-shavar_sbin0 -> 295 bytes
-rw-r--r--chrome/test/data/safe_browsing/old/updates/023goog-phish-shavar_sbin0 -> 580 bytes
-rw-r--r--chrome/test/data/safe_browsing/old/updates/024goog-phish-shavar_sbin0 -> 1512 bytes
-rw-r--r--chrome/test/data/safe_browsing/old/updates/025goog-phish-shavar_sbin0 -> 358 bytes
-rw-r--r--chrome/test/data/safe_browsing/old/updates/026goog-phish-shavar_sbin0 -> 305 bytes
-rw-r--r--chrome/test/data/safe_browsing/old/updates/027goog-phish-shavar_sbin0 -> 182 bytes
-rw-r--r--chrome/test/data/safe_browsing/old/updates/028goog-phish-shavar_sbin0 -> 2542 bytes
-rw-r--r--chrome/test/data/safe_browsing/old/updates/029goog-phish-shavar_sbin0 -> 322 bytes
-rw-r--r--chrome/test/data/safe_browsing/old/updates/030goog-phish-shavar_sbin0 -> 396 bytes
-rw-r--r--chrome/test/data/safe_browsing/old/updates/031goog-phish-shavar_sbin0 -> 357 bytes
-rw-r--r--chrome/test/data/safe_browsing/old/updates/032goog-phish-shavar_sbin0 -> 379 bytes
-rw-r--r--chrome/test/data/safe_browsing/old/updates/033goog-phish-shavar_sbin0 -> 494 bytes
-rw-r--r--chrome/test/data/safe_browsing/old/updates/034goog-phish-shavar_sbin0 -> 10839 bytes
-rw-r--r--chrome/test/data/safe_browsing/old/updates/035goog-phish-shavar_sbin0 -> 11796 bytes
-rw-r--r--chrome/test/data/safe_browsing/old/updates/036goog-phish-shavar_sbin0 -> 12724 bytes
-rw-r--r--chrome/test/data/safe_browsing/old/updates/037goog-phish-shavar_sbin0 -> 3133 bytes
-rw-r--r--chrome/test/data/safe_browsing/old/updates/038goog-phish-shavar_abin0 -> 7835 bytes
-rw-r--r--chrome/test/data/safe_browsing/old/updates/039goog-phish-shavar_abin0 -> 10287 bytes
-rw-r--r--chrome/test/data/safe_browsing/old/updates/040goog-phish-shavar_abin0 -> 12242 bytes
-rw-r--r--chrome/test/data/safe_browsing/old/updates/041goog-phish-shavar_abin0 -> 12879 bytes
-rw-r--r--chrome/test/data/safe_browsing/old/updates/042goog-phish-shavar_abin0 -> 12572 bytes
-rw-r--r--chrome/test/data/save_page/1.css3
-rw-r--r--chrome/test/data/save_page/1.pngbin0 -> 1285 bytes
-rw-r--r--chrome/test/data/save_page/a.htm10
-rw-r--r--chrome/test/data/save_page/b.htm12
-rw-r--r--chrome/test/data/serializer_nested_test.js17
-rw-r--r--chrome/test/data/serializer_test.js8
-rw-r--r--chrome/test/data/serializer_test_nowhitespace.js1
-rw-r--r--chrome/test/data/server-unavailable.html1
-rw-r--r--chrome/test/data/server-unavailable.html.mock-http-headers2
-rw-r--r--chrome/test/data/session_history/bot1.html6
-rw-r--r--chrome/test/data/session_history/bot2.html6
-rw-r--r--chrome/test/data/session_history/bot3.html7
-rw-r--r--chrome/test/data/session_history/form.html31
-rw-r--r--chrome/test/data/session_history/fragment.html12
-rw-r--r--chrome/test/data/session_history/frames.html45
-rw-r--r--chrome/test/data/session_history/no-title.html1
-rw-r--r--chrome/test/data/session_history/post.html28
-rw-r--r--chrome/test/data/session_history/replace.html4
-rw-r--r--chrome/test/data/session_history/top.html8
-rw-r--r--chrome/test/data/ssl/bad_iframe.html10
-rw-r--r--chrome/test/data/ssl/google.html4
-rw-r--r--chrome/test/data/ssl/google_files/logo.gifbin0 -> 8558 bytes
-rw-r--r--chrome/test/data/ssl/page_with_dynamic_mixed_contents.html36
-rw-r--r--chrome/test/data/ssl/page_with_mixed_contents.html9
-rw-r--r--chrome/test/data/ssl/page_with_refs.html21
-rw-r--r--chrome/test/data/ssl/page_with_unsafe_contents.html30
-rw-r--r--chrome/test/data/ssl/set_foo.js1
-rw-r--r--chrome/test/data/sync_xmlhttprequest.html32
-rw-r--r--chrome/test/data/sync_xmlhttprequest_during_unload.html20
-rw-r--r--chrome/test/data/title1.html4
-rw-r--r--chrome/test/data/title2.html4
-rw-r--r--chrome/test/data/viewsource/test.html11
-rw-r--r--chrome/test/data/window.close.html53
-rw-r--r--chrome/test/debugger/debugger_unittests.py50
-rwxr-xr-xchrome/test/debugger/debugger_unittests.sh9
-rw-r--r--chrome/test/debugger/test_protocol.js293
-rw-r--r--chrome/test/injection_test_dll.h51
-rw-r--r--chrome/test/interactive_ui/SConscript132
-rw-r--r--chrome/test/interactive_ui/interactive_ui.vcproj197
-rw-r--r--chrome/test/mini_installer_test/SConscript111
-rw-r--r--chrome/test/mini_installer_test/chrome_mini_installer.cc310
-rw-r--r--chrome/test/mini_installer_test/chrome_mini_installer.h105
-rw-r--r--chrome/test/mini_installer_test/mini_installer_test.vcproj176
-rw-r--r--chrome/test/mini_installer_test/mini_installer_test_constants.cc51
-rw-r--r--chrome/test/mini_installer_test/mini_installer_test_constants.h54
-rw-r--r--chrome/test/mini_installer_test/test.cc58
-rw-r--r--chrome/test/page_cycler/SConscript127
-rw-r--r--chrome/test/page_cycler/page_cycler_test.cc328
-rw-r--r--chrome/test/page_cycler/page_cycler_tests.vcproj210
-rw-r--r--chrome/test/perf/mem_usage.cc98
-rw-r--r--chrome/test/perf/mem_usage.h64
-rw-r--r--chrome/test/perf/perftests.cc77
-rw-r--r--chrome/test/perf/perftests.vcproj207
-rw-r--r--chrome/test/perf/url_parse_perftest.cc175
-rw-r--r--chrome/test/plugin/SConscript130
-rw-r--r--chrome/test/plugin/plugin_test.cpp232
-rw-r--r--chrome/test/plugin/plugin_tests.vcproj190
-rw-r--r--chrome/test/reliability/SConscript125
-rw-r--r--chrome/test/reliability/page_load_test.cc600
-rw-r--r--chrome/test/reliability/page_load_test.h41
-rw-r--r--chrome/test/reliability/reliability_test_suite.h50
-rw-r--r--chrome/test/reliability/reliability_tests.vcproj218
-rw-r--r--chrome/test/reliability/run_all_unittests.cc34
-rw-r--r--chrome/test/security_tests/SConscript91
-rw-r--r--chrome/test/security_tests/ipc_security_tests.cc217
-rw-r--r--chrome/test/security_tests/ipc_security_tests.h39
-rw-r--r--chrome/test/security_tests/security_tests.cc87
-rw-r--r--chrome/test/security_tests/security_tests.vcproj169
-rw-r--r--chrome/test/selenium/README2
-rw-r--r--chrome/test/selenium/SConscript122
-rw-r--r--chrome/test/selenium/expected_failures.txt1
-rw-r--r--chrome/test/selenium/selenium_test.cc196
-rw-r--r--chrome/test/selenium/selenium_tests.vcproj198
-rw-r--r--chrome/test/startup/SConscript121
-rw-r--r--chrome/test/startup/feature_startup_test.cc159
-rw-r--r--chrome/test/startup/startup_test.cc152
-rw-r--r--chrome/test/startup/startup_tests.vcproj206
-rw-r--r--chrome/test/tab_switching/SConscript125
-rw-r--r--chrome/test/tab_switching/tab_switching.vcproj198
-rw-r--r--chrome/test/tab_switching/tab_switching_test.cc170
-rw-r--r--chrome/test/test_file_util.cc124
-rw-r--r--chrome/test/test_file_util.h55
-rw-r--r--chrome/test/testing_browser_process.h151
-rw-r--r--chrome/test/testing_profile.cc69
-rw-r--r--chrome/test/testing_profile.h176
-rw-r--r--chrome/test/ui/inspector_controller_uitest.cc73
-rw-r--r--chrome/test/ui/layout_plugin_uitest.cpp73
-rw-r--r--chrome/test/ui/npapi_uitest.cpp281
-rw-r--r--chrome/test/ui/omnibox_uitest.cc203
-rw-r--r--chrome/test/ui/run_all_unittests.cc35
-rw-r--r--chrome/test/ui/sandbox_uitests.cc51
-rw-r--r--chrome/test/ui/ui_test.cc554
-rw-r--r--chrome/test/ui/ui_test.h344
-rw-r--r--chrome/test/ui/ui_test_suite.cc36
-rw-r--r--chrome/test/ui/ui_test_suite.h81
-rw-r--r--chrome/test/ui/ui_tests.vcproj528
-rw-r--r--chrome/test/unit/chrome_test_suite.h90
-rw-r--r--chrome/test/unit/run_all_unittests.cc34
-rw-r--r--chrome/test/unit/unittests.vcproj924
-rw-r--r--chrome/test/unit/win/rundebug.bat5
439 files changed, 25399 insertions, 0 deletions
diff --git a/chrome/test/accessibility/accessibility_tests.cc b/chrome/test/accessibility/accessibility_tests.cc
new file mode 100644
index 0000000..84dee3b
--- /dev/null
+++ b/chrome/test/accessibility/accessibility_tests.cc
@@ -0,0 +1,503 @@
+// 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.
+
+#include <Objbase.h>
+#include <Oleacc.h>
+#include "chrome/test/accessibility/accessibility_util.h"
+#include "chrome/test/ui/ui_test.h"
+#include "chrome/test/automation/browser_proxy.h"
+#include "chrome/test/automation/window_proxy.h"
+#include "chrome/test/automation/tab_proxy.h"
+#include "chrome/app/chrome_dll_resource.h"
+#include "base/win_util.h"
+#include "base/file_util.h"
+#include "googleurl/src/gurl.h"
+#include "net/base/net_util.h"
+
+
+namespace {
+
+#define CHK_RELEASE(obj) { if (obj) { (obj)->Release(); (obj) = NULL; } }
+
+class AccessibilityTest : public UITest {
+ protected:
+ AccessibilityTest() {
+ show_window_ = true;
+ CoInitialize(NULL);
+ }
+ ~AccessibilityTest() {
+ CoUninitialize();
+ }
+};
+} // Namespace.
+
+// Check browser handle and accessibility object browser client.
+// TODO(sridharg): Alter, when accessibility objects for Chrome Window, Application and
+// Client are corrected.
+TEST_F(AccessibilityTest, TestChromeBrowserAccObject) {
+ IAccessible* p_accobj = NULL;
+ HWND hwnd = GetChromeBrowserWnd(&p_accobj);
+ ASSERT_TRUE(NULL != hwnd);
+ ASSERT_TRUE(NULL != p_accobj);
+ CHK_RELEASE(p_accobj);
+}
+
+// Check accessibility object for toolbar and it's properties Name, Role, State.
+// (Add other properties, if their values are fixed all the time.)
+TEST_F(AccessibilityTest, TestChromeToolbarAccObject) {
+ IAccessible* p_accobj = NULL;
+ GetToolbarWnd(&p_accobj);
+ ASSERT_TRUE(NULL != p_accobj);
+
+ // Check Name - "Google Chrome Toolbar".
+ EXPECT_EQ(L"Google Chrome Toolbar", GetName(p_accobj));
+ // Check Role - "tool bar".
+ EXPECT_EQ(L"tool bar", GetRole(p_accobj));
+ // Check State - "focusable"
+ EXPECT_EQ(L"focusable", GetState(p_accobj));
+
+ CHK_RELEASE(p_accobj);
+}
+
+// Check accessibility object for tabstrip and it's properties Name, Role,
+// State. (Add other properties, if their values are fixed all the time.)
+TEST_F(AccessibilityTest, TestChromeTabstripAccObject) {
+ IAccessible* p_accobj = NULL;
+ GetTabStripWnd(&p_accobj);
+ ASSERT_TRUE(NULL != p_accobj);
+
+ // Check Name - "Tabstrip".
+ EXPECT_EQ(L"Tabstrip", GetName(p_accobj));
+ // Check Role - "grouping".
+ EXPECT_EQ(L"grouping", GetRole(p_accobj));
+ // Check State - "focusable"
+ EXPECT_EQ(L"focusable", GetState(p_accobj));
+
+ CHK_RELEASE(p_accobj);
+}
+
+// Check Browser buttons and their Name, Role, State.
+TEST_F(AccessibilityTest, TestChromeButtons) {
+ HRESULT hr = S_OK;
+ IAccessible* p_accobj = NULL;
+ VARIANT button;
+
+ // Get browser accessibility object.
+ IAccessible* p_browser = NULL;
+ GetChromeBrowserWnd(&p_browser);
+ ASSERT_TRUE(NULL != p_browser);
+
+ // Check Minimize button and it's Name, Role, State.
+ hr = GetBrowserMinimizeButton(&p_accobj, &button);
+ // It is not complete accessible object, as it is element.
+ ASSERT_TRUE(S_FALSE == hr);
+ ASSERT_TRUE(NULL == p_accobj);
+ ASSERT_TRUE(VT_I4 == button.vt);
+ // Read it's properties.
+ EXPECT_EQ(L"Minimize", GetName(p_browser, button));
+ EXPECT_EQ(L"push button", GetRole(p_browser, button));
+ EXPECT_EQ(L"focusable", GetState(p_browser, button));
+ CHK_RELEASE(p_accobj);
+
+ // Check Maximize button and it's Name, Role, State.
+ GetBrowserMaximizeButton(&p_accobj, &button);
+ // It is an element and not complete accessible object.
+ ASSERT_TRUE(S_FALSE == hr);
+ ASSERT_TRUE(NULL == p_accobj);
+ ASSERT_TRUE(VT_I4 == button.vt);
+ // Read it's properties.
+ EXPECT_EQ(L"Maximize", GetName(p_browser, button));
+ EXPECT_EQ(L"push button", GetRole(p_browser, button));
+ EXPECT_EQ(L"focusable", GetState(p_browser, button));
+ CHK_RELEASE(p_accobj);
+
+ // Check Restore button and it's Name, Role, State.
+ GetBrowserRestoreButton(&p_accobj, &button);
+ // It is an element and not complete accessible object.
+ ASSERT_TRUE(S_FALSE == hr);
+ ASSERT_TRUE(NULL == p_accobj);
+ ASSERT_TRUE(VT_I4 == button.vt);
+ // Read it's properties.
+ EXPECT_EQ(L"Restore", GetName(p_browser, button));
+ EXPECT_EQ(L"push button", GetRole(p_browser, button));
+ EXPECT_EQ(L"focusable, invisible", GetState(p_browser, button));
+ CHK_RELEASE(p_accobj);
+
+ // Check Close button and it's Name, Role, State.
+ GetBrowserCloseButton(&p_accobj, &button);
+ // It is an element and not complete accessible object.
+ ASSERT_TRUE(S_FALSE == hr);
+ ASSERT_TRUE(NULL == p_accobj);
+ ASSERT_TRUE(VT_I4 == button.vt);
+ // Read it's properties.
+ EXPECT_EQ(L"Close", GetName(p_browser, button));
+ EXPECT_EQ(L"push button", GetRole(p_browser, button));
+ EXPECT_EQ(L"focusable", GetState(p_browser, button));
+ CHK_RELEASE(p_accobj);
+
+ CHK_RELEASE(p_browser);
+}
+
+// Check Star button and their Name, Role, State.
+TEST_F(AccessibilityTest, TestStarButton) {
+ HRESULT hr = S_OK;
+ IAccessible* p_accobj = NULL;
+ VARIANT button;
+
+ // Get toolbar accessibility object.
+ IAccessible* p_toolbar = NULL;
+ GetToolbarWnd(&p_toolbar);
+ ASSERT_TRUE(NULL != p_toolbar);
+
+ // Check button and it's Name, Role, State.
+ hr = GetStarButton(&p_accobj, &button);
+ // It is not complete accessible object, as it is element.
+ ASSERT_TRUE(S_FALSE == hr);
+ ASSERT_TRUE(NULL == p_accobj);
+ ASSERT_TRUE(VT_I4 == button.vt);
+ // Read it's properties.
+ EXPECT_EQ(L"Bookmark", GetName(p_toolbar, button));
+ EXPECT_EQ(L"push button", GetRole(p_toolbar, button));
+ EXPECT_EQ(L"focusable", GetState(p_toolbar, button));
+ CHK_RELEASE(p_accobj);
+
+ CHK_RELEASE(p_toolbar);
+}
+
+// Check Star button and their Name, Role, State.
+TEST_F(AccessibilityTest, TestStarBtnStatusOnNewTab) {
+ HRESULT hr = S_OK;
+ IAccessible* p_accobj = NULL;
+ VARIANT button;
+
+ // Get toolbar accessibility object.
+ IAccessible* p_toolbar = NULL;
+ GetToolbarWnd(&p_toolbar);
+ ASSERT_TRUE(NULL != p_toolbar);
+
+ // Check button and it's Name, Role, State.
+ hr = GetStarButton(&p_accobj, &button);
+ // It is not a complete accessible object, as it is element.
+ ASSERT_TRUE(S_FALSE == hr);
+ ASSERT_TRUE(NULL == p_accobj);
+ ASSERT_TRUE(VT_I4 == button.vt);
+ EXPECT_EQ(L"focusable", GetState(p_toolbar, button));
+
+ // Now, check Star status in different situations.
+ scoped_ptr<BrowserProxy> window(automation()->GetBrowserWindow(0));
+ ASSERT_TRUE(window.get());
+
+ // Set URL and check button status.
+ scoped_ptr<TabProxy> tab1(window->GetTab(0));
+ ASSERT_TRUE(tab1.get());
+ std::wstring test_file1 = test_data_directory_;
+ file_util::AppendToPath(&test_file1, L"title1.html");
+ tab1->NavigateToURL(net_util::FilePathToFileURL(test_file1));
+ Sleep(kWaitForActionMsec);
+ EXPECT_EQ(L"focusable", GetState(p_toolbar, button));
+
+ // Add empty new tab and check status.
+ int old_tab_count = -1;
+ ASSERT_TRUE(window->GetTabCount(&old_tab_count));
+ ASSERT_TRUE(window->ApplyAccelerator(IDC_NEWTAB));
+ int new_tab_count;
+ ASSERT_TRUE(window->WaitForTabCountToChange(old_tab_count, &new_tab_count,
+ 5000));
+ // Check tab count.
+ ASSERT_GE(new_tab_count, old_tab_count);
+ // Also, check accessibility object's children.
+ Sleep(1000);
+ EXPECT_EQ(L"focusable", GetState(p_toolbar, button)); // ???
+
+ // Add new tab with URL and check status.
+ old_tab_count = new_tab_count;
+ std::wstring test_file2 = test_data_directory_;
+ file_util::AppendToPath(&test_file2, L"title1.html");
+ ASSERT_TRUE(window->AppendTab(net_util::FilePathToFileURL(test_file2)));
+ ASSERT_TRUE(window->WaitForTabCountToChange(old_tab_count, &new_tab_count,
+ 5000));
+ // Check tab count. Also, check accessibility object's children.
+ ASSERT_GE(new_tab_count, old_tab_count);
+ Sleep(kWaitForActionMsec);
+ EXPECT_EQ(L"focusable", GetState(p_toolbar, button));
+
+ CHK_RELEASE(p_toolbar);
+}
+
+// Check Back button and their Name, Role, State.
+TEST_F(AccessibilityTest, TestBackButton) {
+ HRESULT hr = S_OK;
+ IAccessible* p_accobj = NULL;
+ VARIANT button;
+
+ // Get toolbar accessibility object.
+ IAccessible* p_toolbar = NULL;
+ GetToolbarWnd(&p_toolbar);
+ ASSERT_TRUE(NULL != p_toolbar);
+
+ // Check button and it's Name, Role, State.
+ hr = GetBackButton(&p_accobj, &button);
+ // It is not a complete accessible object, as it is element.
+ ASSERT_TRUE(S_FALSE == hr);
+ ASSERT_TRUE(NULL == p_accobj);
+ ASSERT_TRUE(VT_I4 == button.vt);
+
+ // Read it's properties.
+ EXPECT_EQ(L"Back", GetName(p_toolbar, button));
+ EXPECT_EQ(L"drop down button", GetRole(p_toolbar, button));
+ // State "has popup" only supported in XP and higher.
+ if (win_util::GetWinVersion() > win_util::WINVERSION_2000) {
+ EXPECT_EQ(L"has popup, focusable, unavailable",
+ GetState(p_toolbar, button));
+ } else {
+ EXPECT_EQ(L"focusable, unavailable", GetState(p_toolbar, button));
+ }
+ CHK_RELEASE(p_accobj);
+
+ CHK_RELEASE(p_toolbar);
+}
+
+// Check Back button and their Name, Role, State.
+// This test is disabled. See bug 1119183.
+TEST_F(AccessibilityTest, DISABLED_TestBackBtnStatusOnNewTab) {
+ HRESULT hr = S_OK;
+ IAccessible* p_accobj = NULL;
+ VARIANT button;
+
+ // Get toolbar accessibility object.
+ IAccessible* p_toolbar = NULL;
+ GetToolbarWnd(&p_toolbar);
+ ASSERT_TRUE(NULL != p_toolbar);
+
+ // Check button and it's Name, Role, State.
+ hr = GetBackButton(&p_accobj, &button);
+ // It is not complete accessible object, as it is element.
+ ASSERT_TRUE(S_FALSE == hr);
+ ASSERT_TRUE(NULL == p_accobj);
+ ASSERT_TRUE(VT_I4 == button.vt);
+ // State "has popup" only supported in XP and higher.
+ if (win_util::GetWinVersion() > win_util::WINVERSION_2000) {
+ EXPECT_EQ(L"has popup, focusable, unavailable",
+ GetState(p_toolbar, button));
+ } else {
+ EXPECT_EQ(L"focusable, unavailable", GetState(p_toolbar, button));
+ }
+
+ // Now check Back status in different situations.
+ scoped_ptr<BrowserProxy> window(automation()->GetBrowserWindow(0));
+ ASSERT_TRUE(window.get());
+ int old_tab_count = -1;
+ int new_tab_count = -1;
+
+ // Set URL and check button status.
+ scoped_ptr<TabProxy> tab1(window->GetTab(0));
+ ASSERT_TRUE(tab1.get());
+ std::wstring test_file1 = test_data_directory_;
+ file_util::AppendToPath(&test_file1, L"title1.html");
+ tab1->NavigateToURL(net_util::FilePathToFileURL(test_file1));
+ Sleep(kWaitForActionMsec);
+ if (win_util::GetWinVersion() > win_util::WINVERSION_2000) {
+ EXPECT_EQ(L"has popup, focusable",
+ GetState(p_toolbar, button));
+ } else {
+ EXPECT_EQ(L"focusable", GetState(p_toolbar, button));
+ }
+ // Go Back and check status.
+ window->ApplyAccelerator(IDC_BACK);
+ Sleep(kWaitForActionMsec);
+ if (win_util::GetWinVersion() > win_util::WINVERSION_2000) {
+ EXPECT_EQ(L"has popup, focusable, unavailable",
+ GetState(p_toolbar, button));
+ } else {
+ EXPECT_EQ(L"focusable, unavailable", GetState(p_toolbar, button));
+ }
+
+ // Add empty new tab and check status.
+ ASSERT_TRUE(window->GetTabCount(&old_tab_count));
+ ASSERT_TRUE(window->ApplyAccelerator(IDC_NEWTAB));
+ ASSERT_TRUE(window->WaitForTabCountToChange(old_tab_count, &new_tab_count,
+ 5000));
+ // Check tab count. Also, check accessibility object's children.
+ ASSERT_GE(new_tab_count, old_tab_count);
+ if (win_util::GetWinVersion() > win_util::WINVERSION_2000) {
+ EXPECT_EQ(L"has popup, focusable, unavailable",
+ GetState(p_toolbar, button));
+ } else {
+ EXPECT_EQ(L"focusable, unavailable", GetState(p_toolbar, button));
+ }
+
+ // Add new tab with URL and check status.
+ old_tab_count = new_tab_count;
+ std::wstring test_file2 = test_data_directory_;
+ file_util::AppendToPath(&test_file2, L"title1.html");
+ ASSERT_TRUE(window->AppendTab(net_util::FilePathToFileURL(test_file2)));
+ ASSERT_TRUE(window->WaitForTabCountToChange(old_tab_count, &new_tab_count,
+ 5000));
+ // Check tab count. Also, check accessibility object's children.
+ ASSERT_GE(new_tab_count, old_tab_count);
+ Sleep(kWaitForActionMsec);
+ if (win_util::GetWinVersion() > win_util::WINVERSION_2000) {
+ EXPECT_EQ(L"has popup, focusable, unavailable",
+ GetState(p_toolbar, button));
+ } else {
+ EXPECT_EQ(L"focusable, unavailable", GetState(p_toolbar, button));
+ }
+
+ CHK_RELEASE(p_toolbar);
+}
+
+// Check Forward button and their Name, Role, State.
+TEST_F(AccessibilityTest, TestForwardButton) {
+ HRESULT hr = S_OK;
+ IAccessible* p_accobj = NULL;
+ VARIANT button;
+
+ // Get toolbar accessibility object.
+ IAccessible* p_toolbar = NULL;
+ GetToolbarWnd(&p_toolbar);
+ ASSERT_TRUE(NULL != p_toolbar);
+
+ // Check button and it's Name, Role, State.
+ hr = GetForwardButton(&p_accobj, &button);
+ // It is not complete accessible object, as it is element.
+ ASSERT_TRUE(S_FALSE == hr);
+ ASSERT_TRUE(NULL == p_accobj);
+ ASSERT_TRUE(VT_I4 == button.vt);
+ // Read it's properties.
+ EXPECT_EQ(L"Forward", GetName(p_toolbar, button));
+ EXPECT_EQ(L"drop down button", GetRole(p_toolbar, button));
+ // State "has popup" only supported in XP and higher.
+ if (win_util::GetWinVersion() > win_util::WINVERSION_2000) {
+ EXPECT_EQ(L"has popup, focusable, unavailable",
+ GetState(p_toolbar, button));
+ } else {
+ EXPECT_EQ(L"focusable, unavailable", GetState(p_toolbar, button));
+ }
+ CHK_RELEASE(p_accobj);
+
+ CHK_RELEASE(p_toolbar);
+}
+
+// Check Back button and their Name, Role, State.
+// This test is disabled. See bug 1119183.
+TEST_F(AccessibilityTest, DISABLED_TestForwardBtnStatusOnNewTab) {
+ HRESULT hr = S_OK;
+ IAccessible* p_accobj = NULL;
+ VARIANT button;
+
+ // Get toolbar accessibility object.
+ IAccessible* p_toolbar = NULL;
+ GetToolbarWnd(&p_toolbar);
+ ASSERT_TRUE(NULL != p_toolbar);
+
+ // Check button and it's Name, Role, State.
+ hr = GetForwardButton(&p_accobj, &button);
+ // It is not complete accessible object, as it is element.
+ ASSERT_TRUE(S_FALSE == hr);
+ ASSERT_TRUE(NULL == p_accobj);
+ ASSERT_TRUE(VT_I4 == button.vt);
+ // State "has popup" only supported in XP and higher.
+ if (win_util::GetWinVersion() > win_util::WINVERSION_2000) {
+ EXPECT_EQ(L"has popup, focusable, unavailable",
+ GetState(p_toolbar, button));
+ } else {
+ EXPECT_EQ(L"focusable, unavailable", GetState(p_toolbar, button));
+ }
+
+ // Now check Back status in different situations.
+ scoped_ptr<BrowserProxy> window(automation()->GetBrowserWindow(0));
+ ASSERT_TRUE(window.get());
+ int old_tab_count = -1;
+ int new_tab_count = -1;
+
+ // Set URL and check button status.
+ scoped_ptr<TabProxy> tab1(window->GetTab(0));
+ ASSERT_TRUE(tab1.get());
+ std::wstring test_file1 = test_data_directory_;
+ file_util::AppendToPath(&test_file1, L"title1.html");
+ tab1->NavigateToURL(net_util::FilePathToFileURL(test_file1));
+ Sleep(kWaitForActionMsec);
+ if (win_util::GetWinVersion() > win_util::WINVERSION_2000) {
+ EXPECT_EQ(L"has popup, focusable, unavailable",
+ GetState(p_toolbar, button));
+ } else {
+ EXPECT_EQ(L"focusable, unavailable", GetState(p_toolbar, button));
+ }
+ // Go Back and check status.
+ window->ApplyAccelerator(IDC_BACK);
+ Sleep(kWaitForActionMsec);
+ if (win_util::GetWinVersion() > win_util::WINVERSION_2000) {
+ EXPECT_EQ(L"has popup, focusable",
+ GetState(p_toolbar, button));
+ } else {
+ EXPECT_EQ(L"focusable", GetState(p_toolbar, button));
+ }
+ // Go Forward and check status.
+ window->ApplyAccelerator(IDC_FORWARD);
+ Sleep(kWaitForActionMsec);
+ if (win_util::GetWinVersion() > win_util::WINVERSION_2000) {
+ EXPECT_EQ(L"has popup, focusable, unavailable",
+ GetState(p_toolbar, button));
+ } else {
+ EXPECT_EQ(L"focusable, unavailable", GetState(p_toolbar, button));
+ }
+
+ // Add empty new tab and check status.
+ ASSERT_TRUE(window->GetTabCount(&old_tab_count));
+ ASSERT_TRUE(window->ApplyAccelerator(IDC_NEWTAB));
+ ASSERT_TRUE(window->WaitForTabCountToChange(old_tab_count, &new_tab_count,
+ 5000));
+ // Check tab count.
+ ASSERT_GE(new_tab_count, old_tab_count);
+ if (win_util::GetWinVersion() > win_util::WINVERSION_2000) {
+ EXPECT_EQ(L"has popup, focusable, unavailable",
+ GetState(p_toolbar, button));
+ } else {
+ EXPECT_EQ(L"focusable, unavailable", GetState(p_toolbar, button));
+ }
+
+ // Add new tab with URL and check status.
+ old_tab_count = new_tab_count;
+ std::wstring test_file2 = test_data_directory_;
+ file_util::AppendToPath(&test_file2, L"title1.html");
+ ASSERT_TRUE(window->AppendTab(net_util::FilePathToFileURL(test_file2)));
+ ASSERT_TRUE(window->WaitForTabCountToChange(old_tab_count, &new_tab_count,
+ 5000));
+ // Check tab count.
+ ASSERT_GE(new_tab_count, old_tab_count);
+ Sleep(kWaitForActionMsec);
+ if (win_util::GetWinVersion() > win_util::WINVERSION_2000) {
+ EXPECT_EQ(L"has popup, focusable, unavailable",
+ GetState(p_toolbar, button));
+ } else {
+ EXPECT_EQ(L"focusable, unavailable", GetState(p_toolbar, button));
+ }
+
+ CHK_RELEASE(p_toolbar);
+} \ No newline at end of file
diff --git a/chrome/test/accessibility/accessibility_util.cc b/chrome/test/accessibility/accessibility_util.cc
new file mode 100644
index 0000000..43a79a8
--- /dev/null
+++ b/chrome/test/accessibility/accessibility_util.cc
@@ -0,0 +1,620 @@
+// 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.
+
+#include "accessibility_util.h"
+#include "constants.h"
+#include "chrome/common/win_util.h"
+#include "chrome/common/l10n_util.h"
+#include "chrome/browser/xp_frame.h"
+#include "chrome/browser/vista_frame.h"
+#include "generated_resources.h"
+
+VARIANT g_var_self = {VT_I4, CHILDID_SELF};
+
+HWND GetChromeBrowserWnd(IAccessible** ppi_access) {
+ HRESULT hr = S_OK;
+ HWND hwnd = NULL;
+ BSTR str_name;
+ std::wstring str_role;
+
+ const std::wstring product_name = l10n_util::GetString(IDS_PRODUCT_NAME);
+
+ // Get Chrome window handle.
+ if (win_util::ShouldUseVistaFrame()) {
+ hwnd = FindWindow(VISTA_FRAME_CLASSNAME, NULL);
+ } else {
+ hwnd = FindWindow(XP_FRAME_CLASSNAME, NULL);
+ }
+
+ if (NULL == hwnd) {
+ if (ppi_access)
+ *ppi_access = NULL;
+ return hwnd;
+ }
+
+ // Get accessibility object for Chrome, only if requested.
+ if (!ppi_access) {
+ return hwnd;
+ }
+ *ppi_access = NULL;
+
+ // Get accessibility object for Chrome Main Window. If failed to get it,
+ // return only window handle.
+ IAccessible *pi_acc_root_win = NULL;
+ hr = AccessibleObjectFromWindow(hwnd, OBJID_WINDOW, IID_IAccessible,
+ reinterpret_cast<void**>
+ (&pi_acc_root_win));
+ if ((S_OK != hr) || !pi_acc_root_win) {
+ return hwnd;
+ }
+
+
+ // Confirm if it is Chrome window using it's accessibility object's
+ // Name and Role property. If it's not the desired object, return only
+ // window handle.
+ hr = pi_acc_root_win->get_accName(g_var_self, &str_name);
+ if ((S_OK != hr) || (!str_name) ||
+ (0 != _wcsicmp(str_name, product_name.c_str())) ) {
+ CHK_RELEASE(pi_acc_root_win);
+ return hwnd;
+ }
+ str_role = GetRole(pi_acc_root_win);
+ if (0 != str_role.compare(BROWSER_WIN_ROLE)) {
+ CHK_RELEASE(pi_acc_root_win);
+ return hwnd;
+ }
+
+ // Get accessibility object for Chrome Window. If failed to get it,
+ // return only window handle.
+ INT64 child_cnt = GetChildCount(pi_acc_root_win);
+ VARIANT *var_array_child =
+ reinterpret_cast<VARIANT*>(calloc(size_t(child_cnt),
+ sizeof(VARIANT)));
+
+ if (!var_array_child) {
+ CHK_RELEASE(pi_acc_root_win);
+ return hwnd;
+ }
+
+ hr = GetChildrenArray(pi_acc_root_win, var_array_child);
+ if (S_OK != hr) {
+ CHK_RELEASE(pi_acc_root_win);
+ return hwnd;
+ }
+
+ // Fetch desired child (Chrome window) of Chrome Main Window.
+ IAccessible *pi_acc_app = NULL;
+ GetChildObject(pi_acc_root_win, var_array_child[CHROME_APP_ACC_INDEX],
+ &pi_acc_app);
+ if (!pi_acc_app) {
+ CHK_RELEASE(pi_acc_app);
+ return hwnd;
+ }
+
+ // Confirm if it is Chrome application using it's accessibility object's
+ // Name and Role property. If it's not the desired object, return only
+ // window handle.
+ hr = pi_acc_app->get_accName(g_var_self, &str_name);
+ if ((S_OK != hr) || (!str_name) ||
+ (0 != _wcsicmp(str_name, product_name.c_str())) ) {
+ CHK_RELEASE(pi_acc_app);
+ CHK_RELEASE(pi_acc_root_win);
+ return hwnd;
+ }
+ str_role = GetRole(pi_acc_app);
+ if (0 != str_role.compare(BROWSER_APP_ROLE)) {
+ CHK_RELEASE(pi_acc_app);
+ CHK_RELEASE(pi_acc_root_win);
+ return hwnd;
+ }
+
+ // Get accessibility object for Chrome Client. If failed, return only
+ // window handle.
+ hr = GetChildrenArray(pi_acc_app, var_array_child);
+ if (S_OK != hr) {
+ CHK_RELEASE(pi_acc_app);
+ CHK_RELEASE(pi_acc_root_win);
+ return hwnd;
+ }
+
+ // Chrome Window has only one child which is Chrome Client.
+ GetChildObject(pi_acc_app, var_array_child[CHROME_CLIENT_ACC_INDEX],
+ ppi_access);
+
+ // Confirm if it is Chrome client using it's accessibility object's Name
+ // and Role property. If it's not the desired object, return only window
+ // handle.
+ hr = (*ppi_access)->get_accName(g_var_self, &str_name);
+ if ((S_OK != hr) || (!str_name) ||
+ (0 != _wcsicmp(str_name, product_name.c_str())) ) {
+ CHK_RELEASE(*ppi_access);
+ }
+ str_role = GetRole(*ppi_access);
+ if (0 != str_role.compare(BROWSER_CLIENT_ROLE)) {
+ CHK_RELEASE(*ppi_access);
+ }
+
+ CHK_RELEASE(pi_acc_app);
+ CHK_RELEASE(pi_acc_root_win);
+ return hwnd;
+}
+
+HRESULT GetChildWndOf(std::wstring parent_name, unsigned int child_index,
+ IAccessible** ppi_access, VARIANT* child_var_id) {
+ HRESULT hr = S_OK;
+
+ // Validate input and initialize.
+ if (!ppi_access && !child_var_id)
+ return E_INVALIDARG;
+ if (ppi_access)
+ *ppi_access = NULL;
+ if (child_var_id)
+ VariantInit(child_var_id);
+
+ // Get accessibility object and window handle for Chrome parent.
+ IAccessible *pi_parent = NULL;
+ if (0 == parent_name.compare(BROWSER_STR))
+ GetChromeBrowserWnd(&pi_parent);
+ if (0 == parent_name.compare(TOOLBAR_STR))
+ GetToolbarWnd(&pi_parent);
+ if (0 == parent_name.compare(TABSTRIP_STR))
+ GetTabStripWnd(&pi_parent);
+
+ if (!pi_parent)
+ return E_FAIL;
+
+ // Validate child index.
+ INT64 child_cnt = GetChildCount(pi_parent);
+ if (child_index >= child_cnt) {
+ CHK_RELEASE(pi_parent);
+ VariantClear(child_var_id);
+ return E_INVALIDARG;
+ }
+
+ // Get array of child items of parent object.
+ VARIANT *var_array_child =
+ reinterpret_cast<VARIANT*>(calloc(size_t(child_cnt), sizeof(VARIANT)));
+ if (var_array_child) {
+ hr = GetChildrenArray(pi_parent, var_array_child);
+ if (S_OK == hr) {
+ // Fetch Tabstrip which is child_index'th child of parent object.
+ if (ppi_access) {
+ hr = GetChildObject(pi_parent, var_array_child[child_index],
+ ppi_access);
+ }
+ if (child_var_id) {
+ VariantCopy(child_var_id, var_array_child+child_index);
+ }
+ }
+ free(var_array_child);
+ }
+
+ CHK_RELEASE(pi_parent);
+ return hr;
+}
+
+HRESULT GetTabStripWnd(IAccessible** ppi_access) {
+ return GetChildWndOf(BROWSER_STR, TABSTRIP_ACC_INDEX, ppi_access, NULL);
+}
+
+HRESULT GetToolbarWnd(IAccessible** ppi_access) {
+ return GetChildWndOf(BROWSER_STR, TOOLBAR_ACC_INDEX, ppi_access, NULL);
+}
+
+HRESULT GetBrowserMinimizeButton(IAccessible** ppi_access,
+ VARIANT* child_var_id) {
+ return GetChildWndOf(BROWSER_STR, CHROME_MIN_ACC_INDEX, ppi_access,
+ child_var_id);
+}
+
+HRESULT GetBrowserMaximizeButton(IAccessible** ppi_access,
+ VARIANT* child_var_id) {
+ return GetChildWndOf(BROWSER_STR, CHROME_MAX_ACC_INDEX, ppi_access,
+ child_var_id);
+}
+
+HRESULT GetBrowserRestoreButton(IAccessible** ppi_access,
+ VARIANT* child_var_id) {
+ return GetChildWndOf(BROWSER_STR, CHROME_RESTORE_ACC_INDEX, ppi_access,
+ child_var_id);
+}
+
+HRESULT GetBrowserCloseButton(IAccessible** ppi_access,
+ VARIANT* child_var_id) {
+ return GetChildWndOf(BROWSER_STR, CHROME_CLOSE_ACC_INDEX, ppi_access,
+ child_var_id);
+}
+
+HRESULT GetStarButton(IAccessible** ppi_access, VARIANT* child_var_id) {
+ return GetChildWndOf(TOOLBAR_STR, STAR_BTN_INDEX, ppi_access, child_var_id);
+}
+
+HRESULT GetBackButton(IAccessible** ppi_access, VARIANT* child_var_id) {
+ return GetChildWndOf(TOOLBAR_STR, BACK_BTN_INDEX, ppi_access, child_var_id);
+}
+
+HRESULT GetForwardButton(IAccessible** ppi_access, VARIANT* child_var_id) {
+ return GetChildWndOf(TOOLBAR_STR, FORWARD_BTN_INDEX, ppi_access,
+ child_var_id);
+}
+
+HWND GetAddressBarWnd(IAccessible** ppi_access) {
+ HWND hwnd = NULL;
+ HWND hwnd_addr_bar = NULL;
+
+ // // Initialize, if requested.
+ if (ppi_access) {
+ *ppi_access = NULL;
+ }
+
+ // Get window handle for Chrome Browser.
+ hwnd = GetChromeBrowserWnd(NULL);
+ if (NULL != hwnd) {
+ // Get AddressBar/OmniBox (edit box) window handle.
+ hwnd_addr_bar = FindWindowEx(hwnd, 0, CHROME_AUTOCOMPLETE_EDIT, NULL);
+
+ // Get accessibility object for address bar, if requested.
+ if (ppi_access && hwnd_addr_bar) {
+ AccessibleObjectFromWindow(hwnd_addr_bar, OBJID_WINDOW, IID_IAccessible,
+ reinterpret_cast<void**>(ppi_access));
+ }
+ }
+
+ return hwnd_addr_bar;
+}
+
+HWND GetFindTextWnd(IAccessible** ppi_access) {
+ HWND hwnd = NULL;
+ HWND hwnd_find = NULL;
+
+ // Initialize, if requested.
+ if (ppi_access) {
+ *ppi_access = NULL;
+ }
+
+ // Get window handle for Chrome Browser.
+ hwnd = GetChromeBrowserWnd(NULL);
+ if (NULL != hwnd) {
+ // Get handle of a window, which is contains edit box for Find string.
+ hwnd_find = FindWindowEx(hwnd, 0, CHROME_HWND_VIEW_CONTAINER, NULL);
+
+ // Get accessibility object, if requested.
+ if (ppi_access && hwnd_find) {
+ AccessibleObjectFromWindow(hwnd_find, OBJID_WINDOW, IID_IAccessible,
+ reinterpret_cast<void**>(ppi_access));
+ }
+ }
+
+ return hwnd_find;
+}
+
+HWND GetAuthWnd(IAccessible** ppi_access) {
+ HWND hwnd = NULL;
+ HWND hwnd_tab = NULL;
+ HWND hwnd_auth = NULL;
+
+ // Initialize, if requested.
+ if (ppi_access) {
+ *ppi_access = NULL;
+ }
+
+ // Get window handle for Chrome Browser.
+ hwnd = GetChromeBrowserWnd(NULL);
+ if (NULL != hwnd) {
+ // Get window handle for tab.
+ hwnd_tab = FindWindowEx(hwnd, 0, CHROME_TAB_CONTENTS, NULL);
+ if (!hwnd_tab)
+ return hwnd_auth;
+
+ // Get handle for Authentication window.
+ hwnd_auth = FindWindowEx(hwnd_tab, 0, CHROME_HWND_VIEW_CONTAINER,
+ AUTH_TITLE);
+
+ // Get accessibility object, if requested.
+ if (ppi_access && hwnd_auth) {
+ AccessibleObjectFromWindow(hwnd_auth, OBJID_WINDOW, IID_IAccessible,
+ reinterpret_cast<void**>(ppi_access));
+ }
+ }
+
+ return hwnd_auth;
+}
+
+HRESULT GetChildObject(IAccessible* pi_access, VARIANT var_child,
+ IAccessible** ppi_child_access) {
+ HRESULT hr = S_OK;
+ IDispatch *p_dispatch = NULL;
+
+ // Validate input.
+ if ( (pi_access == NULL) ||
+ (ppi_child_access == NULL) ) {
+ return E_INVALIDARG;
+ }
+
+ // Check the child type and fetch object accordingly.
+ if (var_child.vt == VT_DISPATCH) {
+ var_child.pdispVal->
+ QueryInterface(IID_IAccessible,
+ reinterpret_cast<void**>(ppi_child_access));
+ } else if (var_child.vt == VT_I4) {
+ hr = pi_access->get_accChild(var_child, &p_dispatch);
+ if ( (hr == S_OK) &&
+ (p_dispatch != NULL) ) {
+ p_dispatch->QueryInterface(IID_IAccessible,
+ reinterpret_cast<void**>(ppi_child_access));
+ CHK_RELEASE(p_dispatch);
+ }
+ }
+
+ return hr;
+}
+
+HRESULT GetParentObject(IAccessible* pi_access,
+ IAccessible** ppi_parent_access) {
+ HRESULT hr = S_OK;
+ IDispatch *p_dispatch = NULL;
+
+ // Validate input.
+ if ( (pi_access == NULL) ||
+ (ppi_parent_access == NULL) ) {
+ return E_INVALIDARG;
+ }
+
+ // Fetch parent object.
+ hr = pi_access->get_accParent(&p_dispatch);
+ if ( (hr == S_OK) &&
+ (p_dispatch != NULL) ) {
+ p_dispatch->QueryInterface(IID_IAccessible,
+ reinterpret_cast<void**>(ppi_parent_access));
+ CHK_RELEASE(p_dispatch);
+ }
+
+ return hr;
+}
+
+INT64 GetChildCount(IAccessible* pi_access) {
+ HRESULT hr = S_OK;
+ long child_cnt = 0;
+
+ // Validate input. Object can have 0 children. So return -1 on invalid input.
+ if (pi_access == NULL) {
+ return -1;
+ }
+
+ // Get child count.
+ pi_access->get_accChildCount(&child_cnt);
+ return child_cnt;
+}
+
+HRESULT GetChildrenArray(IAccessible* pi_access, VARIANT* var_array_child) {
+ HRESULT hr = S_OK;
+ INT64 child_start = 0;
+ long child_obtained = 0;
+ INT64 child_cnt = GetChildCount(pi_access);
+
+ // Validate input.
+ if ((pi_access == NULL) || (var_array_child == NULL)) {
+ return E_INVALIDARG;
+ }
+
+ // Validate every item and initialize it.
+ int i = 0;
+ for (; (i < child_cnt) && (var_array_child+i); i++) {
+ VariantInit(var_array_child+i);
+ }
+
+ // If all items in array are not initialized, return error.
+ if (i != child_cnt) {
+ return E_INVALIDARG;
+ }
+
+ // Get IDs of child items.
+ AccessibleChildren(pi_access,
+ LONG(child_start),
+ LONG(child_cnt),
+ var_array_child,
+ &child_obtained);
+ return hr;
+}
+
+HRESULT ActivateWnd(IAccessible *pi_access, HWND hwnd) {
+ HRESULT hr = S_OK;
+
+ // Select and focus the object, if accessibility object is specified.
+ if (pi_access) {
+ hr = pi_access->accSelect(SELFLAG_TAKEFOCUS | SELFLAG_TAKESELECTION,
+ g_var_self);
+ }
+
+ // Send message to window, if window handle is specified.
+ if (hwnd) {
+ SetActiveWindow(hwnd);
+ }
+
+ return hr;
+}
+
+BSTR GetTabName(INT64 tab_index) {
+ HRESULT hr = S_OK;
+ BSTR str_name;
+
+ // Validate tab index specified.
+ if (tab_index < 1)
+ return NULL;
+
+ // Get accessibility object for Tabstrip.
+ IAccessible *pi_acc_strip = NULL;
+ GetTabStripWnd(&pi_acc_strip);
+
+ // Get Tab from Tabstrip and return it's Name.
+ if (pi_acc_strip) {
+ INT64 child_cnt = GetChildCount(pi_acc_strip);
+ VARIANT *var_array_child =
+ reinterpret_cast<VARIANT*>(calloc(size_t(child_cnt), sizeof(VARIANT)));
+ if (var_array_child) {
+ // Get tab object. tab_index = index in child array, because first child
+ // in tabstrip is '+' button.
+ hr = GetChildrenArray(pi_acc_strip, var_array_child);
+ if (S_OK == hr) {
+ IAccessible *pi_access_temp = NULL;
+ hr = GetChildObject(pi_acc_strip, var_array_child[tab_index],
+ &pi_access_temp);
+ if ((S_OK == hr) &&
+ (var_array_child[tab_index].vt == VT_DISPATCH) &&
+ (pi_access_temp) ) {
+ hr = pi_access_temp->get_accName(g_var_self, &str_name);
+ } else if (var_array_child[tab_index].vt == VT_I4) {
+ hr = pi_acc_strip->get_accName(var_array_child[1], &str_name);
+ }
+ CHK_RELEASE(pi_acc_strip);
+ return str_name;
+ }
+ }
+
+ CHK_RELEASE(pi_acc_strip);
+ }
+
+ return NULL;
+}
+
+INT64 GetTabCnt() {
+ // Get accessibility object for Tabstrip.
+ IAccessible *pi_acc_strip = NULL;
+ GetTabStripWnd(&pi_acc_strip);
+
+ // If Tabstrip is invalid, return -1, to indicate error.
+ if (!pi_acc_strip) {
+ return -1;
+ }
+
+ // Get child count.
+ INT64 child_cnt = 0;
+ if (pi_acc_strip) {
+ child_cnt = GetChildCount(pi_acc_strip);
+ CHK_RELEASE(pi_acc_strip);
+ }
+
+ // Don't count 1st child as it is '+' button.
+ return (child_cnt-1);
+}
+
+std::wstring GetName(IAccessible* pi_access, VARIANT child) {
+ HRESULT hr = S_OK;
+
+ // Validate input.
+ if (NULL == pi_access) {
+ return std::wstring();
+ }
+
+ // Get Name.
+ BSTR name;
+ hr = pi_access->get_accName(child, &name);
+ if (S_OK != hr)
+ return std::wstring();
+
+ return std::wstring(name);
+}
+
+std::wstring GetRole(IAccessible* pi_access, VARIANT child) {
+ HRESULT hr = S_OK;
+ LPTSTR role_str = NULL;
+
+ // Validate input.
+ if (NULL == pi_access) {
+ return std::wstring();
+ }
+
+ // Get Role.
+ VARIANT role;
+ VariantInit(&role);
+ hr = pi_access->get_accRole(child, &role);
+ if (S_OK != hr || VT_I4 != role.vt) {
+ VariantClear(&role);
+ return std::wstring();
+ }
+
+ // Get Role string.
+ unsigned int role_length = GetRoleText(role.lVal, NULL, 0);
+ role_str = (LPTSTR)calloc(role_length + 1, sizeof(TCHAR));
+ if (role_str)
+ GetRoleText(role.lVal, role_str, role_length + 1);
+
+ VariantClear(&role);
+ return std::wstring(role_str);
+}
+
+std::wstring GetState(IAccessible* pi_access, VARIANT child) {
+ HRESULT hr = S_OK;
+ LPTSTR state_str = NULL;
+ std::wstring complete_state;
+
+ // Validate input.
+ if (NULL == pi_access) {
+ return std::wstring();
+ }
+
+ // Get State.
+ VARIANT state;
+ VariantInit(&state);
+ hr = pi_access->get_accState(child, &state);
+ if (S_OK != hr || VT_I4 != state.vt) {
+ VariantClear(&state);
+ return std::wstring();
+ }
+
+ // Treat the "normal" state separately.
+ if (state.vt == 0) {
+ unsigned int state_length = GetStateText(state.lVal, NULL, 0);
+ state_str = (LPTSTR)calloc(state_length + 1, sizeof(TCHAR));
+ if (state_str) {
+ GetStateText(state.lVal, state_str, state_length + 1);
+ complete_state = std::wstring(state_str);
+ }
+ } else {
+ // Number of bits.
+ UINT bit_cnt = 32;
+ // Convert state flags to comma separated list.
+ for (DWORD dwStateBit = 0x80000000; bit_cnt; bit_cnt--, dwStateBit >>= 1) {
+ if (state.lVal & dwStateBit) {
+ unsigned int state_length = GetStateText(dwStateBit, NULL, 0);
+ state_str = (LPTSTR)calloc(state_length + 1, sizeof(TCHAR));
+ if (state_str) {
+ GetStateText(dwStateBit, state_str, state_length + 1);
+ if (complete_state.length() > 0)
+ complete_state.append(L", ");
+ complete_state.append(state_str);
+ free(state_str);
+ }
+ }
+ }
+ }
+
+ VariantClear(&state);
+ return complete_state;
+}
diff --git a/chrome/test/accessibility/accessibility_util.h b/chrome/test/accessibility/accessibility_util.h
new file mode 100644
index 0000000..77d0f03
--- /dev/null
+++ b/chrome/test/accessibility/accessibility_util.h
@@ -0,0 +1,136 @@
+// 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.
+
+#ifndef CHROME_TEST_ACCISSIBILITY_ACCISSIBILITY_UTIL_H__
+#define CHROME_TEST_ACCISSIBILITY_ACCISSIBILITY_UTIL_H__
+
+#include <Oleacc.h>
+#include <iostream>
+
+///////////////////////////////////////////////////////////////////////////////
+// Functions and Globals which are using IAccessible interface.
+// These are the wrappers to fetch accessible object interface and properties.
+///////////////////////////////////////////////////////////////////////////////
+
+// Variant ID pointing to object itself.
+extern VARIANT g_var_self;
+
+// Returns window handle to Chrome Browser. Retrives it's(having role as
+// client) IAccessible pointer, if requested.
+HWND GetChromeBrowserWnd(IAccessible** ppi_access);
+
+// Returns IAccessible pointer of object's child window, provided parent's name
+// and it's 0 based child index. If child is element and not complete object,
+// it's variant id is returned with S_FALSE.
+HRESULT GetChildWndOf(std::wstring parent_name, unsigned int child_index,
+ IAccessible** ppi_access, VARIANT* child_var_id);
+
+// Returns IAccessible pointer for Tabstrip. It does not have window handle.
+HRESULT GetTabStripWnd(IAccessible** ppi_access);
+
+// Returns IAccessible pointer for Toolbar. It does not have window handle.
+HRESULT GetToolbarWnd(IAccessible** ppi_access);
+
+// Returns handle to OmniBox(AddressBar) and IAccessible pointer, if requested.
+HWND GetAddressBarWnd(IAccessible** ppi_access);
+
+// Returns handle to Find box and IAccessible pointer, if requested.
+HWND GetFindTextWnd(IAccessible** ppi_access);
+
+// Returns handle to authentication dialog and IAccessible pointer, if
+// requested.
+HWND GetAuthWnd(IAccessible** ppi_access);
+
+// Fetches IAccessible pointer for a child of given the IAccessible pointer
+// and desired child id.
+HRESULT GetChildObject(IAccessible* pi_access, VARIANT var_child,
+ IAccessible** ppi_child_access);
+
+// Fetches IAccessible pointer for a parent of specified IAccessible pointer.
+HRESULT GetParentObject(IAccessible* pi_access,
+ IAccessible** ppi_parent_access);
+
+// Returns no. of child items of specified IAccessible pointer. If input
+// parameter is NULL, -1 is returned.
+INT64 GetChildCount(IAccessible* pi_access);
+
+// Extracts (VARIANT)array of child items of specified IAccessible pointer.
+HRESULT GetChildrenArray(IAccessible* pi_access, VARIANT* var_array_child);
+
+// Activates specified window using IAccessible pointer and/or window handle.
+HRESULT ActivateWnd(IAccessible *pi_access, HWND hwnd);
+
+// Returns title of tab whose index is specified. Tab index starts from 1.
+BSTR GetTabName(INT64 tab_index);
+
+// Returns no. of tabs in tabstrip. If processing fails, it returns -1.
+INT64 GetTabCnt();
+
+// Returns Name of specified IAccessible pointer or it's child specified by
+// variant.
+std::wstring GetName(IAccessible* pi_access, VARIANT child = g_var_self);
+
+// Returns Role of specified IAccessible pointer or it's child specified by
+// variant.
+std::wstring GetRole(IAccessible* pi_access, VARIANT child = g_var_self);
+
+// Returns State of specified IAccessible pointer or it's child specified by
+// variant.
+std::wstring GetState(IAccessible* pi_access, VARIANT child = g_var_self);
+
+// Returns IAccessible pointer for Chrome Minimize Button. It does not have
+// window handle.
+HRESULT GetBrowserMinimizeButton(IAccessible** ppi_access,
+ VARIANT* child_var_id);
+
+// Returns IAccessible pointer for Chrome Maximize Button. It does not have
+// window handle.
+HRESULT GetBrowserMaximizeButton(IAccessible** ppi_access,
+ VARIANT* child_var_id);
+
+// Returns IAccessible pointer for Chrome Restore Button. It does not have
+// window handle.
+HRESULT GetBrowserRestoreButton(IAccessible** ppi_access,
+ VARIANT* child_var_id);
+
+// Returns IAccessible pointer for Chrome Close Button. It does not have
+// window handle.
+HRESULT GetBrowserCloseButton(IAccessible** ppi_access, VARIANT* child_var_id);
+
+// Returns IAccessible pointer for Star Button. It does not have window handle.
+HRESULT GetStarButton(IAccessible** ppi_access, VARIANT* child_var_id);
+
+// Returns IAccessible pointer for Back Button. It does not have window handle.
+HRESULT GetBackButton(IAccessible** ppi_access, VARIANT* child_var_id);
+
+// Returns IAccessible pointer for Forward Button. It does not have window
+// handle.
+HRESULT GetForwardButton(IAccessible** ppi_access, VARIANT* child_var_id);
+
+#endif // CHROME_TEST_ACCISSIBILITY_ACCISSIBILITY_UTIL_H__
diff --git a/chrome/test/accessibility/browser_impl.cc b/chrome/test/accessibility/browser_impl.cc
new file mode 100644
index 0000000..50eb9f7
--- /dev/null
+++ b/chrome/test/accessibility/browser_impl.cc
@@ -0,0 +1,551 @@
+// 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.
+
+#include "chrome/test/accessibility/browser_impl.h"
+
+#include <shellapi.h>
+
+#include "chrome/test/accessibility/accessibility_util.h"
+#include "chrome/test/accessibility/keyboard_util.h"
+#include "chrome/test/accessibility/registry_util.h"
+
+bool CBrowserImpl::Launch(void) {
+ // TODO: Check if chrome already running.
+ BSTR chrome_path = SysAllocString(GetChromeExePath());
+ BOOL bool_return = FALSE;
+
+ // Initialize and fill up structure.
+ SHELLEXECUTEINFO shell_execute_info;
+ memset(&shell_execute_info, 0, sizeof(SHELLEXECUTEINFO));
+ shell_execute_info.cbSize = sizeof(SHELLEXECUTEINFO);
+ // To get Process handle.
+ shell_execute_info.fMask = SEE_MASK_NOCLOSEPROCESS;
+ shell_execute_info.nShow = SW_SHOW;
+ shell_execute_info.lpFile =
+ reinterpret_cast<TCHAR*>(malloc(sizeof(TCHAR) *
+ SysStringLen(chrome_path)));
+ _tcscpy_s((TCHAR*)(shell_execute_info.lpFile), SysStringLen(chrome_path),
+ chrome_path);
+
+ // Execute.
+ bool_return = ShellExecuteEx(&shell_execute_info);
+
+ if (bool_return &&
+ (INT64(shell_execute_info.hInstApp) > 32) ) {
+ // TODO: Maintain instance and process handle.
+
+ // Maintain active tab index.
+ SetActiveTabIndex(1);
+
+ // Create initial tab collection.
+ UpdateTabCollection();
+
+ // Chrome launched.
+ return true;
+ }
+
+ return false;
+}
+
+bool CBrowserImpl::Quit(void) {
+ // Cleanup.
+ EraseTabCollection();
+
+ // Send close message to browser window.
+ HWND hwnd = GetChromeBrowserWnd(NULL);
+ if (!hwnd)
+ return false;
+ SendMessage(hwnd, WM_CLOSE, 0, 0);
+ return true;
+}
+
+bool CBrowserImpl::ActivateTab(const INT64 index) {
+ // Validate index specified.
+ if (index < 1) {
+ return false;
+ }
+
+ // Goto next tab till focused at desired tab.
+ // TODO: Change implementation when DoDefaultAction() for Tab is exported.
+ while (active_tab_index_ != index) {
+ GoToNextTab(NULL);
+ }
+ return true;
+}
+
+bool CBrowserImpl::GetActiveTabURL(BSTR* url) {
+ // Validate input.
+ if (!url)
+ return false;
+
+ // TODO: Implement.
+ return true;
+}
+
+bool CBrowserImpl::GetActiveTabTitle(BSTR* title) {
+ if (!title)
+ return false;
+
+ BSTR tab_title = SysAllocString(GetTabName(active_tab_index_));
+ *title = SysAllocString(tab_title);
+ return true;
+}
+
+bool CBrowserImpl::GetActiveTabIndex(INT64* index) {
+ if (!index)
+ return false;
+
+ *index = active_tab_index_;
+ return true;
+}
+
+void CBrowserImpl::SetActiveTabIndex(INT64 index) {
+ if ((index >= MIN_TAB_INDEX_DIGIT) && (index <= GetTabCnt()))
+ active_tab_index_ = index;
+ return;
+}
+
+bool CBrowserImpl::GetActiveTab(CTabImpl** tab) {
+ return GetTab(active_tab_index_, tab);
+}
+
+bool CBrowserImpl::GetTabCount(INT64* count) {
+ if (!count)
+ return false;
+
+ *count = GetTabCnt();
+ return true;
+}
+
+bool CBrowserImpl::GetBrowserProcessCount(INT64* count) {
+ if (!count)
+ return false;
+
+ // TODO: Add your implementation code here
+
+ return true;
+}
+
+bool CBrowserImpl::GetBrowserTitle(BSTR* title) {
+ if (!title)
+ return false;
+
+ HWND hwnd = GetChromeBrowserWnd(NULL);
+ if (!hwnd)
+ return false;
+
+ int text_length = GetWindowTextLength(hwnd);
+ *title = SysAllocStringLen(NULL, text_length);
+ GetWindowText(hwnd, *title, text_length);
+ return true;
+}
+
+bool CBrowserImpl::AddTab(CTabImpl** tab) {
+ // Add new tab.
+ HWND hwnd = GetChromeBrowserWnd(NULL);
+ if (!hwnd)
+ return false;
+ ClickKey(hwnd, VK_CONTROL, 'T');
+
+ // Update active tab index.
+ INT64 new_tab_index = GetTabCnt();
+ if (-1 == new_tab_index)
+ return false;
+ SetActiveTabIndex(new_tab_index);
+
+ // Fill object.
+ CTabImpl *new_tab = new CTabImpl();
+ if (!new_tab)
+ return false;
+ ChromeTab* tab_data = new_tab->InitTabData();
+ new_tab->PutIndex(new_tab_index);
+ new_tab->PutTitle(GetTabName(new_tab_index));
+ new_tab->SetBrowser(this);
+
+ // Update tab collection.
+ tab_collection_.push_back(tab_data);
+
+ // Create tab object, if requested.
+ if (tab)
+ *tab = new_tab;
+
+ return true;
+}
+
+bool CBrowserImpl::GetTab(const INT64 index, CTabImpl** tab) {
+ // Create tab object, if requested.
+ if (!tab)
+ return false;
+
+ if (index > GetTabCnt())
+ return false;
+
+ *tab = new CTabImpl();
+ if (!*tab)
+ return false;
+
+ // Fill object.
+ ChromeTab* tab_data = (*tab)->InitTabData();
+ (*tab)->PutIndex(index);
+ (*tab)->PutTitle(GetTabName(index));
+ (*tab)->SetBrowser(this);
+
+ return true;
+}
+
+bool CBrowserImpl::GoToTab(const INT64 index, CTabImpl** tab) {
+ // Validate input.
+ if (index > MAX_TAB_INDEX_DIGIT)
+ return false;
+
+ // Stay on current tab, if index doesnot exist.
+ if ((0 == index) || (GetTabCnt() < index))
+ return true;
+
+ // Move to a tab (indexed 1 to 9).
+ IAccessible *pi_access = NULL;
+ HWND hwnd = GetChromeBrowserWnd(&pi_access);
+ if (pi_access && hwnd) {
+ // Activate main window and operate key Ctrl+digit.
+ ActivateWnd(pi_access, hwnd);
+ ClickKey(hwnd, VK_CONTROL, WORD('0'+index));
+ CHK_RELEASE(pi_access);
+
+ // Set focused tab index.
+ active_tab_index_ = index;
+ // Return tab object.
+ if (tab) {
+ return GetTab(active_tab_index_, tab);
+ }
+ }
+
+ return false;
+}
+
+bool CBrowserImpl::GoToNextTab(CTabImpl** tab) {
+ IAccessible *pi_access = NULL;
+ HWND hwnd = GetChromeBrowserWnd(&pi_access);
+ if (pi_access && hwnd) {
+ // Activate main window and operate key Ctrl+Tab.
+ ActivateWnd(pi_access, hwnd);
+ ClickKey(hwnd, VK_CONTROL, VK_TAB);
+ CHK_RELEASE(pi_access);
+
+ // Set focused tab index.
+ if (active_tab_index_ == GetTabCnt()) {
+ active_tab_index_ = 1;
+ } else {
+ active_tab_index_ = active_tab_index_ + 1;
+ }
+
+ // Return tab object.
+ if (tab) {
+ return GetTab(active_tab_index_, tab);
+ }
+ }
+
+ return false;
+}
+
+bool CBrowserImpl::GoToPrevTab(CTabImpl** tab) {
+ IAccessible *pi_access = NULL;
+ HWND hwnd = GetChromeBrowserWnd(&pi_access);
+ if (pi_access && hwnd) {
+ // Activate main window and operate key Ctrl+Tab.
+ ActivateWnd(pi_access, hwnd);
+ ClickKey(hwnd, VK_SHIFT, VK_CONTROL, VK_TAB);
+ CHK_RELEASE(pi_access);
+
+ // Set focused tab index.
+ if (active_tab_index_ == 1) {
+ active_tab_index_ = GetTabCnt();
+ } else {
+ active_tab_index_ = active_tab_index_ - 1;
+ }
+
+ // Return tab object.
+ if (tab) {
+ return GetTab(active_tab_index_, tab);
+ }
+ }
+
+ return false;
+}
+
+bool CBrowserImpl::WaitForChromeToBeVisible(const INT64 interval,
+ const INT64 timeout,
+ bool* visible) {
+ IAccessible *pi_access = NULL;
+ INT64 time_elapsed = 0;
+ *visible = false;
+
+ // Check and wait.
+ while (timeout >= time_elapsed) {
+ GetTabStripWnd(&pi_access);
+ if (pi_access) {
+ *visible = true;
+ CHK_RELEASE(pi_access);
+ return true;
+ }
+ Sleep(DWORD(interval));
+ time_elapsed = time_elapsed + interval;
+ }
+
+ return false;
+}
+
+bool CBrowserImpl::WaitForTabCountToChange(const INT64 interval,
+ const INT64 timeout,
+ bool* changed) {
+ // TODO: Add your implementation code here
+
+ return true;
+}
+
+bool CBrowserImpl::WaitForTabToBecomeActive(const INT64 index,
+ const INT64 interval,
+ const INT64 timeout,
+ bool* activated) {
+ // TODO: Add your implementation code here
+
+ return true;
+}
+
+bool CBrowserImpl::ApplyAccelerator(VARIANT keys) {
+ // Input should be -array of enum or strings
+ // or -IDispatch (jscript array object).
+ if ((keys.vt != (VT_ARRAY|VT_BSTR)) && // Array of string values.
+ (keys.vt != (VT_ARRAY|VT_I4)) && // Array of enum values.
+ (!(keys.vt & VT_DISPATCH)) ) { // Object.
+ return false;
+ }
+
+ // Array to store keys in a single combination. Currently, valid keyboard
+ // -input combination can constitute of at the most 3 keys.
+ KEYBD_KEYS key_value[3];
+ // Initialize key count.
+ int key_cnt = 0;
+ // Get variant array from object.
+ IDispatch *disp = NULL;
+
+ // Not array of string values or integers.
+ if ((keys.vt != (VT_ARRAY|VT_BSTR)) &&
+ (keys.vt != (VT_ARRAY|VT_I4)) ) {
+ // Retrive IDispatch.
+ if (keys.vt & VT_BYREF)
+ disp = *(keys.ppdispVal);
+ else
+ disp = keys.pdispVal;
+
+ // Get array length.
+ DISPPARAMS params;
+ FillMemory(&params, sizeof(DISPPARAMS), 0);
+ VARIANT res;
+ DISPID id;
+ LPOLESTR ln = L"length";
+ if (S_OK != disp->GetIDsOfNames(IID_NULL, &ln, 1, LOCALE_USER_DEFAULT,
+ &id)) {
+ return false;
+ }
+
+ if (S_OK != disp->Invoke(id, IID_NULL, LOCALE_USER_DEFAULT,
+ DISPATCH_PROPERTYGET, &params, &res, NULL,
+ NULL)) {
+ return false;
+ }
+
+ VARIANT len;
+ VariantInit(&len);
+ VariantChangeType(&len, &res, 0, VT_I4);
+ if (len.lVal > 3)
+ return false;
+ key_cnt = len.lVal;
+
+ // Add elements to safe array.
+ for (int i = 0; i < len.lVal; i++) {
+ // Fetch element.
+ wchar_t wstr[5];
+ memset(wstr, 0, 5*sizeof(wchar_t));
+ wsprintf(wstr, L"%d", i);
+ LPOLESTR olestr = wstr;
+
+ if (S_OK != disp->GetIDsOfNames(IID_NULL, &olestr, 1,
+ LOCALE_USER_DEFAULT, &id)) {
+ return false;
+ }
+
+ if (S_OK != disp->Invoke(id, IID_NULL, LOCALE_USER_DEFAULT,
+ DISPATCH_PROPERTYGET, &params, &res, NULL,
+ NULL)) {
+ return false;
+ }
+
+ VARIANT value;
+ VariantInit(&value);
+ VariantChangeType(&value, &res, 0, VT_BSTR);
+
+ // Translate and add key to array.
+ key_value[i] = GetKeybdKeysVal(value.bstrVal);
+
+ VariantClear(&value);
+ }
+
+ VariantClear(&len);
+ } else {
+ // Directly fetch array.
+ SAFEARRAY *key_safe = NULL;
+ key_safe = V_ARRAY(&keys);
+
+ // Operate on Variant Array.
+ HRESULT hr = S_OK;
+ LONG cElements, lLBound, lUBound;
+
+ // Array is not 1-dimentional.
+ if (SafeArrayGetDim(key_safe) != 1)
+ return false;
+
+ // Get array bounds.
+ hr = SafeArrayGetLBound(key_safe, 1, &lLBound);
+ if (S_OK !=hr)
+ return false;
+ hr = SafeArrayGetUBound(key_safe, 1, &lUBound);
+ if (S_OK !=hr)
+ return false;
+
+ // Key combination can be of maximum 3 keys.
+ cElements = lUBound-lLBound+1;
+ if (cElements > 3)
+ return false;
+ key_cnt = cElements;
+
+ // Read the data in array.
+ if (keys.vt == (VT_ARRAY|VT_I4)) {
+ KEYBD_KEYS *read_keys;
+ hr = SafeArrayAccessData(key_safe,
+ reinterpret_cast<void **>(&read_keys));
+ if (S_OK !=hr)
+ return false;
+ for (int i = 0; i < cElements; i++) {
+ key_value[i] = read_keys[i];
+ }
+ } else if (keys.vt == (VT_ARRAY|VT_BSTR)) {
+ BSTR *key_str_value;
+ hr = SafeArrayAccessData(key_safe,
+ reinterpret_cast<void **>(&key_str_value));
+ if (S_OK !=hr)
+ return false;
+
+ // Translate and add key to array.
+ for (int i = 0; i < cElements; i++) {
+ key_value[i] = GetKeybdKeysVal(key_str_value[i]);
+ }
+ }
+ }
+
+ // Focus on main window and operate keys.
+ IAccessible *pi_access = NULL;
+ HWND hwnd = GetChromeBrowserWnd(&pi_access);
+ if (pi_access || hwnd)
+ ActivateWnd(pi_access, hwnd);
+
+ if (1 == key_cnt)
+ ClickKey(hwnd, key_value[0]);
+ else if (2 == key_cnt)
+ ClickKey(hwnd, key_value[0], key_value[1]);
+ else if (3 == key_cnt)
+ ClickKey(hwnd, key_value[0], key_value[1], key_value[2]);
+
+ CHK_RELEASE(pi_access);
+
+ return true;
+}
+
+void CBrowserImpl::UpdateTabCollection(void) {
+ // Get tab count and browser title.
+ INT64 tab_cnt = GetTabCnt();
+ BSTR browser_title;
+ GetBrowserTitle(&browser_title);
+
+ // Check tab-collection size and no. of existing tabs,
+ // work accordingly.
+
+ // First time creation
+ if (0 == tab_collection_.size()) {
+ EraseTabCollection();
+ for (int i = 0; i < tab_cnt; i++) {
+ tab_collection_[i]->index_ = i + 1;
+ tab_collection_[i]->title_ =
+ SysAllocString(GetTabName(tab_collection_[i]->index_));
+ if (browser_title == tab_collection_[i]->title_) {
+ active_tab_index_ = tab_collection_[i]->index_;
+ }
+ }
+ }
+
+ // TODO: If tabs are swapped.
+ // Add implementation here.
+}
+
+void CBrowserImpl::EraseTabCollection(void) {
+ std::vector<ChromeTab*>::iterator tab_iterator;
+ for (tab_iterator = tab_collection_.begin();
+ tab_iterator != tab_collection_.end();
+ tab_iterator++) {
+ // Relese memory used for data.
+ CHK_DELETE(*tab_iterator);
+ }
+ tab_collection_.clear();
+}
+
+void CBrowserImpl::CloseTabFromCollection(INT64 index) {
+ std::vector <ChromeTab*>::size_type collection_size = tab_collection_.size();
+ // Validate tab index.
+ if ((index < MIN_TAB_INDEX_DIGIT) ||
+ (static_cast<unsigned int>(index) > collection_size) )
+ return;
+
+ // Index starts from 1.
+ tab_collection_.erase(tab_collection_.begin() + static_cast<int>(index) - 1);
+
+ // Now update tab collection data.
+ collection_size = tab_collection_.size();
+
+ // Check if tab deleted is last tab.
+ if (index-1 == collection_size) {
+ // Change active tab index, only if tab deleted is last tab.
+ active_tab_index_ = index - 1;
+ } else {
+ for (std::vector <ChromeTab*>::size_type i =
+ static_cast<unsigned int>(index) - 1;
+ i < collection_size;
+ i++) {
+ tab_collection_[i]->index_--;
+ }
+ }
+}
diff --git a/chrome/test/accessibility/browser_impl.h b/chrome/test/accessibility/browser_impl.h
new file mode 100644
index 0000000..51fda43
--- /dev/null
+++ b/chrome/test/accessibility/browser_impl.h
@@ -0,0 +1,134 @@
+// 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.
+
+#ifndef CHROME_TEST_ACCISSIBILITY_BROWSER_IMPL_H__
+#define CHROME_TEST_ACCISSIBILITY_BROWSER_IMPL_H__
+
+#include <vector>
+
+#include "tab_impl.h"
+
+/////////////////////////////////////////////////////////////////////
+// CBrowserImpl
+// It is a wrapper to Browser specific functionalities.
+// Note:
+// In most of the tasks, keyboard messages are used for now.
+// DoDefaultAction() will be called on accessibility objects,
+// once implementation is available in chrome accessibility server.
+// And keyboard messages will be tested using ApplyAccelerator().
+/////////////////////////////////////////////////////////////////////
+
+class CBrowserImpl {
+ public:
+ CBrowserImpl() {
+ active_tab_index_ = 0;
+ }
+
+ // Starts Chrome. Sets active tab index.
+ bool Launch(void);
+
+ // Closes Chrome.
+ bool Quit(void);
+
+ // Activates the specified tab.
+ bool ActivateTab(const INT64 index);
+
+ // Returns URL of the active tab.
+ bool GetActiveTabURL(BSTR* url);
+
+ // Gets active tab's title.
+ bool GetActiveTabTitle(BSTR* title);
+
+ // Gets active tab index.
+ bool GetActiveTabIndex(INT64* index);
+
+ // Returns active tab object.
+ bool GetActiveTab(CTabImpl** tab);
+
+ // Returns no. of tabs in tabstrip.
+ bool GetTabCount(INT64* count);
+
+ bool GetBrowserProcessCount(INT64* count);
+
+ // Reads browser title, which is also a active tab's title
+ bool GetBrowserTitle(BSTR* title);
+
+ // Adds new tab. Maintain current active tab index.
+ // Returns created tab, if requested.
+ bool AddTab(CTabImpl** tab);
+
+ // Returns tab object of specified index.
+ bool GetTab(const INT64 index, CTabImpl** tab);
+
+ // Activate tab of specified index. Maintain current active tab index.
+ // Returns created tab, if requested.
+ bool GoToTab(const INT64 index, CTabImpl** tab);
+
+ // Move to next tab. Maintain current active tab index.
+ // Returns created tab, if requested.
+ bool GoToNextTab(CTabImpl** tab);
+
+ // Move to previous tab. Maintain current active tab index.
+ // Returns created tab, if requested.
+ bool GoToPrevTab(CTabImpl** tab);
+
+ // Wait for chrome window to be visible. It checks for accessibility object
+ // for tabstrip after every 'interval' for the specified 'timeout'.
+ bool WaitForChromeToBeVisible(const INT64 interval, const INT64 timeout,
+ bool* visible);
+ bool WaitForTabCountToChange(const INT64 interval, const INT64 timeout,
+ bool* changed);
+ bool WaitForTabToBecomeActive(const INT64 index, const INT64 interval,
+ const INT64 timeout, bool* activated);
+
+ // Sends keyboard message. Sends accelerators.
+ bool ApplyAccelerator(VARIANT keys);
+
+ // Sets active tab index.
+ void SetActiveTabIndex(INT64 index);
+
+ // Removed tab from tab collection vector.
+ void CloseTabFromCollection(INT64 index);
+
+ // Updates tab collection vector
+ void UpdateTabCollection(void);
+
+ // Removes tab from tab collection vector.
+ void EraseTabCollection(void);
+
+ private:
+ // Index of active tab.
+ INT64 active_tab_index_;
+
+ // Collection of tab data.
+ std::vector<ChromeTab*> tab_collection_;
+};
+
+
+#endif // CHROME_TEST_ACCISSIBILITY_BROWSER_IMPL_H__
diff --git a/chrome/test/accessibility/constants.h b/chrome/test/accessibility/constants.h
new file mode 100644
index 0000000..bb60d9e
--- /dev/null
+++ b/chrome/test/accessibility/constants.h
@@ -0,0 +1,134 @@
+// 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.
+
+#ifndef CHROME_TEST_ACCISSIBILITY_CONSTANTS_H__
+#define CHROME_TEST_ACCISSIBILITY_CONSTANTS_H__
+
+#include <windows.h>
+#include <tchar.h>
+
+///////////////////////////////////////////////////////////////////
+// Constant Definitations specific to Chrome Accessibility Tests.
+///////////////////////////////////////////////////////////////////
+
+// Safe delete and release operations.
+#define CHK_RELEASE(obj) { if (obj) { (obj)->Release(); (obj) = NULL; } }
+#define CHK_DELETE(obj) { if (obj) { delete (obj); (obj) = NULL; } }
+
+
+// Chrome Accessibility Tests specific strings.
+#define CHROME_PATH _T("C:\\Program Files\\Google\\Chrome\\Chrome.exe")
+#define CHROME_VIEWS_TEXT_FIELD_EDIT _T("ChromeViewsTextFieldEdit")
+#define CHROME_AUTOCOMPLETE_EDIT _T("Chrome_AutocompleteEdit")
+#define CHROME_VIEWS_NATIVE_CTRL_CONTNR _T("ChromeViewsNativeControlContainer")
+#define CHROME_HWND_VIEW_CONTAINER _T("Chrome_HWNDViewContainer_0")
+#define STD_BUTTON _T("Button")
+#define AUTH_TITLE _T("Authentication Required - Chrome")
+#define CHROME_TAB_CONTENTS _T("Chrome_TabContents")
+
+#define BROWSER_WIN_ROLE _T("window")
+#define BROWSER_APP_ROLE _T("application")
+#define BROWSER_CLIENT_ROLE _T("client")
+
+#define CHROME_APP_ACC_INDEX (3)
+#define CHROME_CLIENT_ACC_INDEX (0)
+
+// Chrome Client chidren.
+#define TOOLBAR_ACC_INDEX (0)
+#define TABSTRIP_ACC_INDEX (1)
+#define CHROME_MIN_ACC_INDEX (3)
+#define CHROME_MAX_ACC_INDEX (4)
+#define CHROME_RESTORE_ACC_INDEX (5)
+#define CHROME_CLOSE_ACC_INDEX (6)
+
+// Toolbar children.
+#define BACK_BTN_INDEX (0)
+#define FORWARD_BTN_INDEX (1)
+#define RELOAD_BTN_INDEX (2)
+#define STAR_BTN_INDEX (4)
+#define GO_BTN_INDEX (6)
+#define PAGE_BTN_INDEX (7)
+#define MENU_BTN_INDEX (8)
+
+// Digit limits for tab index which can be used in accelerator.
+#define MAX_TAB_INDEX_DIGIT (9)
+#define MIN_TAB_INDEX_DIGIT (1)
+
+// Object Names.
+#define BROWSER_STR _T("browser")
+#define TOOLBAR_STR _T("toolbar")
+#define TABSTRIP_STR _T("tabstrip")
+#define TAB_STR _T("tab")
+
+// Enums for keyboard keys. These values are directed to virtual-key values.
+enum KEYBD_KEYS {
+ KEY_F3 = VK_F3,
+ KEY_F4 = VK_F4,
+ KEY_F5 = VK_F5,
+ KEY_F6 = VK_F6,
+ KEY_ALT = VK_MENU,
+ KEY_CONTROL = VK_CONTROL,
+ KEY_SHIFT = VK_SHIFT,
+ KEY_ENTER = VK_RETURN,
+ KEY_TAB = VK_TAB,
+ KEY_BACK = VK_BACK,
+ KEY_HOME = VK_HOME,
+ KEY_END = VK_END,
+ KEY_ESC = VK_ESCAPE,
+ KEY_INSERT = VK_INSERT,
+ KEY_DELETE = VK_DELETE,
+ KEY_LEFT = VK_LEFT,
+ KEY_RIGHT = VK_RIGHT,
+ KEY_PLUS = VK_ADD,
+ KEY_MINUS = VK_SUBTRACT,
+ KEY_0 = '0',
+ KEY_1 = '1',
+ KEY_2 = '2',
+ KEY_3 = '3',
+ KEY_4 = '4',
+ KEY_5 = '5',
+ KEY_6 = '6',
+ KEY_7 = '7',
+ KEY_8 = '8',
+ KEY_9 = '9',
+ KEY_D = 'D',
+ KEY_F = 'F',
+ KEY_G = 'G',
+ KEY_K = 'K',
+ KEY_L = 'L',
+ KEY_N = 'N',
+ KEY_O = 'O',
+ KEY_R = 'R',
+ KEY_T = 'T',
+ KEY_W = 'W',
+ KEY_INVALID = -1
+};
+
+
+#endif // CHROME_TEST_ACCISSIBILITY_CONSTANTS_H__
diff --git a/chrome/test/accessibility/keyboard_util.cc b/chrome/test/accessibility/keyboard_util.cc
new file mode 100644
index 0000000..0e42776
--- /dev/null
+++ b/chrome/test/accessibility/keyboard_util.cc
@@ -0,0 +1,219 @@
+// 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.
+
+#include "keyboard_util.h"
+
+void ClickKey(HWND hwnd, WORD key) {
+ INPUT input[2];
+ memset(&input, 0, sizeof(INPUT)*2);
+
+ // Press key.
+ input[0].type = INPUT_KEYBOARD;
+ input[0].ki.wVk = key;
+ input[0].ki.dwFlags = 0;
+
+ // Release key.
+ input[1].type = INPUT_KEYBOARD;
+ input[1].ki.wVk = key;
+ input[1].ki.dwFlags = KEYEVENTF_KEYUP;
+
+ SendInput(2, input, sizeof(INPUT));
+}
+
+void ClickKey(HWND hwnd, WORD extended_key, WORD key) {
+ INPUT input[4];
+ memset(&input, 0, sizeof(INPUT)*4);
+
+ // Press extended key.
+ input[0].type = INPUT_KEYBOARD;
+ input[0].ki.wVk = extended_key;
+ input[0].ki.dwFlags = KEYEVENTF_EXTENDEDKEY;
+
+ // Press key.
+ input[1].type = INPUT_KEYBOARD;
+ input[1].ki.wVk = key;
+ input[1].ki.dwFlags = KEYEVENTF_EXTENDEDKEY;
+
+ // Release key.
+ input[2].type = INPUT_KEYBOARD;
+ input[2].ki.wVk = key;
+ input[2].ki.dwFlags = KEYEVENTF_EXTENDEDKEY|KEYEVENTF_KEYUP;
+
+ // Release key.
+ input[3].type = INPUT_KEYBOARD;
+ input[3].ki.wVk = extended_key;
+ input[3].ki.dwFlags = KEYEVENTF_EXTENDEDKEY|KEYEVENTF_KEYUP;
+
+ SendInput(4, input, sizeof(INPUT));
+}
+
+void ClickKey(HWND hwnd, WORD extended_key1, WORD extended_key2, WORD key) {
+ INPUT input[6];
+ memset(&input, 0, sizeof(INPUT)*6);
+
+ // Press extended key1.
+ input[0].type = INPUT_KEYBOARD;
+ input[0].ki.wVk = extended_key1;
+ input[0].ki.dwFlags = KEYEVENTF_EXTENDEDKEY;
+
+ // Press extended key2.
+ input[1].type = INPUT_KEYBOARD;
+ input[1].ki.wVk = extended_key2;
+ input[1].ki.dwFlags = KEYEVENTF_EXTENDEDKEY;
+
+ // Press key.
+ input[2].type = INPUT_KEYBOARD;
+ input[2].ki.wVk = key;
+ input[2].ki.dwFlags = KEYEVENTF_EXTENDEDKEY;
+
+ // Release key.
+ input[3].type = INPUT_KEYBOARD;
+ input[3].ki.wVk = key;
+ input[3].ki.dwFlags = KEYEVENTF_EXTENDEDKEY|KEYEVENTF_KEYUP;
+
+ // Release extended key2.
+ input[4].type = INPUT_KEYBOARD;
+ input[4].ki.wVk = extended_key2;
+ input[4].ki.dwFlags = KEYEVENTF_EXTENDEDKEY|KEYEVENTF_KEYUP;
+
+ // Release extended key1.
+ input[5].type = INPUT_KEYBOARD;
+ input[5].ki.wVk = extended_key1;
+ input[5].ki.dwFlags = KEYEVENTF_EXTENDEDKEY|KEYEVENTF_KEYUP;
+
+ SendInput(6, input, sizeof(INPUT));
+}
+
+void PressKey(HWND hwnd, WORD key) {
+ SendMessage(hwnd, WM_KEYDOWN, key, 0);
+ SendMessage(hwnd, WM_CHAR, key, 0);
+}
+
+void ReleaseKey(HWND hwnd, WORD key) {
+ SendMessage(hwnd, WM_KEYUP, key, 0);
+}
+
+KEYBD_KEYS GetKeybdKeysVal(BSTR str) {
+ if (0 == wcslen(str))
+ return KEY_INVALID;
+
+ if (0 == _wcsicmp(str, L"F3"))
+ return KEY_F3;
+ if (0 == _wcsicmp(str, L"F4"))
+ return KEY_F4;
+ if (0 == _wcsicmp(str, L"F5"))
+ return KEY_F5;
+ if (0 == _wcsicmp(str, L"F6"))
+ return KEY_F6;
+ if (0 == _wcsicmp(str, L"ALT"))
+ return KEY_ALT;
+ if (0 == _wcsicmp(str, L"ALTER"))
+ return KEY_ALT;
+ if (0 == _wcsicmp(str, L"CTRL"))
+ return KEY_CONTROL;
+ if (0 == _wcsicmp(str, L"CONTROL"))
+ return KEY_CONTROL;
+ if (0 == _wcsicmp(str, L"SHIFT"))
+ return KEY_SHIFT;
+ if (0 == _wcsicmp(str, L"ENTER"))
+ return KEY_ENTER;
+ if (0 == _wcsicmp(str, L"RETURN"))
+ return KEY_ENTER;
+ if (0 == _wcsicmp(str, L"TAB"))
+ return KEY_TAB;
+ if (0 == _wcsicmp(str, L"BACK"))
+ return KEY_BACK;
+ if (0 == _wcsicmp(str, L"HOME"))
+ return KEY_HOME;
+ if (0 == _wcsicmp(str, L"END"))
+ return KEY_END;
+ if (0 == _wcsicmp(str, L"ESC"))
+ return KEY_ESC;
+ if (0 == _wcsicmp(str, L"ESCAPE"))
+ return KEY_ESC;
+ if (0 == _wcsicmp(str, L"INSERT"))
+ return KEY_INSERT;
+ if (0 == _wcsicmp(str, L"INS"))
+ return KEY_INSERT;
+ if (0 == _wcsicmp(str, L"DEL"))
+ return KEY_DELETE;
+ if (0 == _wcsicmp(str, L"DELETE"))
+ return KEY_DELETE;
+ if (0 == _wcsicmp(str, L"LEFT"))
+ return KEY_LEFT;
+ if (0 == _wcsicmp(str, L"RIGHT"))
+ return KEY_RIGHT;
+ if (0 == _wcsicmp(str, L"0"))
+ return KEY_0;
+ if (0 == _wcsicmp(str, L"1"))
+ return KEY_1;
+ if (0 == _wcsicmp(str, L"2"))
+ return KEY_2;
+ if (0 == _wcsicmp(str, L"3"))
+ return KEY_3;
+ if (0 == _wcsicmp(str, L"4"))
+ return KEY_4;
+ if (0 == _wcsicmp(str, L"5"))
+ return KEY_5;
+ if (0 == _wcsicmp(str, L"6"))
+ return KEY_6;
+ if (0 == _wcsicmp(str, L"7"))
+ return KEY_7;
+ if (0 == _wcsicmp(str, L"8"))
+ return KEY_8;
+ if (0 == _wcsicmp(str, L"9"))
+ return KEY_9;
+ if (0 == _wcsicmp(str, L"D"))
+ return KEY_D;
+ if (0 == _wcsicmp(str, L"F"))
+ return KEY_F;
+ if (0 == _wcsicmp(str, L"G"))
+ return KEY_G;
+ if (0 == _wcsicmp(str, L"K"))
+ return KEY_K;
+ if (0 == _wcsicmp(str, L"L"))
+ return KEY_L;
+ if (0 == _wcsicmp(str, L"N"))
+ return KEY_N;
+ if (0 == _wcsicmp(str, L"O"))
+ return KEY_O;
+ if (0 == _wcsicmp(str, L"R"))
+ return KEY_R;
+ if (0 == _wcsicmp(str, L"T"))
+ return KEY_T;
+ if (0 == _wcsicmp(str, L"W"))
+ return KEY_W;
+ if (0 == _wcsicmp(str, L"+"))
+ return KEY_PLUS;
+ if (0 == _wcsicmp(str, L"-"))
+ return KEY_MINUS;
+
+ // No key found.
+ return KEY_INVALID;
+}
diff --git a/chrome/test/accessibility/keyboard_util.h b/chrome/test/accessibility/keyboard_util.h
new file mode 100644
index 0000000..d16b6a9
--- /dev/null
+++ b/chrome/test/accessibility/keyboard_util.h
@@ -0,0 +1,62 @@
+// 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.
+
+#ifndef CHROME_TEST_ACCISSIBILITY_KEYBOARD_UTIL_H__
+#define CHROME_TEST_ACCISSIBILITY_KEYBOARD_UTIL_H__
+
+#include "constants.h"
+
+#include <oleauto.h>
+
+//////////////////////////////////////////////////////
+// Function declarations to automate keyboard events.
+//////////////////////////////////////////////////////
+
+// Enqueue keyboard message for a key. Currently, hwnd is not used.
+void ClickKey(HWND hwnd, WORD key);
+
+// Enqueue keyboard message for a combination of 2 keys. Currently, hwnd is
+// not used.
+void ClickKey(HWND hwnd, WORD key, WORD extended_key);
+
+// Enqueue keyboard message for a combination of 2 keys.
+// Currently, hwnd is not used.
+void ClickKey(HWND hwnd, WORD key, WORD extended_key1, WORD extended_key2);
+
+// Sends key-down message to window.
+void PressKey(HWND hwnd, WORD key);
+
+// Sends key-up message to window.
+void ReleaseKey(HWND hwnd, WORD key);
+
+// Returns native enum values for a key-string specified.
+KEYBD_KEYS GetKeybdKeysVal(BSTR str);
+
+
+#endif // CHROME_TEST_ACCISSIBILITY_KEYBOARD_UTIL_H__
diff --git a/chrome/test/accessibility/registry_util.cc b/chrome/test/accessibility/registry_util.cc
new file mode 100644
index 0000000..287c1df
--- /dev/null
+++ b/chrome/test/accessibility/registry_util.cc
@@ -0,0 +1,37 @@
+// 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.
+
+#include "registry_util.h"
+#include "constants.h"
+
+BSTR GetChromeExePath() {
+ // TODO: once registry contains chrome exe path.
+ BSTR chrome_exe_path = SysAllocString(CHROME_PATH);
+ return chrome_exe_path;
+}
diff --git a/chrome/test/accessibility/registry_util.h b/chrome/test/accessibility/registry_util.h
new file mode 100644
index 0000000..a3024d8
--- /dev/null
+++ b/chrome/test/accessibility/registry_util.h
@@ -0,0 +1,42 @@
+// 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.
+
+#ifndef CHROME_TEST_ACCISSIBILITY_REGISTRY_UTIL_H__
+#define CHROME_TEST_ACCISSIBILITY_REGISTRY_UTIL_H__
+
+//////////////////////////////////////////////////
+// Functions for registry operations.
+//////////////////////////////////////////////////
+
+#include <ocidl.h>
+
+// Reads chrome installation path from registry.
+BSTR GetChromeExePath();
+
+#endif // CHROME_TEST_ACCISSIBILITY_REGISTRY_UTIL_H__
diff --git a/chrome/test/accessibility/tab_impl.cc b/chrome/test/accessibility/tab_impl.cc
new file mode 100644
index 0000000..4393ffc
--- /dev/null
+++ b/chrome/test/accessibility/tab_impl.cc
@@ -0,0 +1,389 @@
+// 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.
+
+#include "browser_impl.h"
+#include "tab_impl.h"
+#include "accessibility_util.h"
+#include "keyboard_util.h"
+#include "constants.h"
+
+bool CTabImpl::Close(void) {
+ IAccessible *pi_access = NULL;
+ HWND hwnd = GetChromeBrowserWnd(&pi_access);
+ if (!pi_access || !hwnd)
+ return false;
+
+ // Activate main window and operate key Ctrl+F4.
+ ActivateWnd(pi_access, hwnd);
+ ClickKey(hwnd, VK_CONTROL, VK_F4);
+ CHK_RELEASE(pi_access);
+
+ // Update tab information in browser object.
+ my_browser_->CloseTabFromCollection(tab_->index_);
+ return true;
+}
+
+bool CTabImpl::GetTitle(BSTR* title) {
+ // Validation.
+ if (!title)
+ return false;
+
+ // Read Tab name and store it in local member and return same value.
+ BSTR tab_title = GetTabName(tab_->index_);
+ *title = SysAllocString(tab_title);
+ tab_->title_ = SysAllocString(tab_title);
+ return true;
+}
+
+bool CTabImpl::SetAddressBarText(const BSTR text) {
+ IAccessible *pi_access = NULL;
+ HWND hwnd_addr_bar = GetAddressBarWnd(&pi_access);
+ if (!pi_access || !hwnd_addr_bar)
+ return false;
+
+ // Activate address bar.
+ ActivateWnd(pi_access, hwnd_addr_bar);
+ // Set text to address bar.
+ SendMessage(hwnd_addr_bar, WM_SETTEXT, 0, LPARAM(text));
+ CHK_RELEASE(pi_access);
+ return true;
+}
+
+bool CTabImpl::NavigateToURL(const BSTR url) {
+ IAccessible *pi_access = NULL;
+ HWND hwnd_addr_bar = GetAddressBarWnd(&pi_access);
+
+ if (!pi_access || !hwnd_addr_bar)
+ return false;
+
+ // Activate address bar.
+ ActivateWnd(pi_access, hwnd_addr_bar);
+ // Set text to address bar.
+ SendMessage(hwnd_addr_bar, WM_SETTEXT, 0, LPARAM(url));
+ // Click Enter. Window is activated above for this.
+ ClickKey(hwnd_addr_bar, VK_RETURN);
+ CHK_RELEASE(pi_access);
+ return true;
+}
+
+bool CTabImpl::FindInPage(const BSTR find_text) {
+ IAccessible *pi_access = NULL;
+ HWND hwnd = GetChromeBrowserWnd(&pi_access);
+ if (!pi_access || !hwnd)
+ return false;
+
+ // Activate main window and operate key 'F3' to invoke Find window.
+ ActivateWnd(pi_access, hwnd);
+ ClickKey(hwnd, VK_F3);
+ CHK_RELEASE(pi_access);
+
+ // If no text is to be searched, return.
+ if (find_text != NULL) {
+ // TODO: Once FindWindow is exported through Accessibility.
+ // Instead of sleep, check if FindWindows exists or not.
+ Sleep(50);
+
+ // Get Find window.
+ pi_access = NULL;
+ hwnd = GetFindTextWnd(&pi_access);
+ if (hwnd) {
+ HWND hwnd_find_edit = FindWindowEx(hwnd, 0,
+ CHROME_VIEWS_TEXT_FIELD_EDIT, 0);
+ if (hwnd_find_edit) {
+ ActivateWnd(pi_access, hwnd);
+ ActivateWnd(NULL, hwnd_find_edit);
+ // Set text in Find window edit box.
+ WCHAR* strTemp =
+ reinterpret_cast<WCHAR*>(calloc(wcslen(find_text), sizeof(WCHAR)));
+ wcscpy_s(strTemp, wcslen(find_text), find_text);
+ for (size_t i = 0; i < wcslen(strTemp); i++) {
+ SendMessage(hwnd_find_edit, WM_KEYDOWN, strTemp[i], 0);
+ SendMessage(hwnd_find_edit, WM_CHAR, strTemp[i], 0);
+ SendMessage(hwnd_find_edit, WM_KEYUP, strTemp[i], 0);
+ }
+ }
+ }
+ }
+ CHK_RELEASE(pi_access);
+
+ return true;
+}
+
+bool CTabImpl::Reload(void) {
+ IAccessible *pi_access = NULL;
+ HWND hwnd = GetChromeBrowserWnd(&pi_access);
+ if (!pi_access || !hwnd)
+ return false;
+
+ // Operate key F5.
+ ActivateWnd(pi_access, hwnd);
+ ClickKey(hwnd, VK_F5);
+ CHK_RELEASE(pi_access);
+ return true;
+}
+
+bool CTabImpl::Duplicate(CTabImpl** tab) {
+ // TODO: Add your implementation code here
+ return true;
+}
+
+bool CTabImpl::IsAuthDialogVisible() {
+ IAccessible *pi_access = NULL;
+ HWND hwnd = GetChromeBrowserWnd(&pi_access);
+ if (!pi_access || !hwnd)
+ return false;
+
+ // Activate main window.
+ ActivateWnd(pi_access, hwnd);
+ CHK_RELEASE(pi_access);
+
+ // Check for Authentication Window.
+ pi_access = NULL;
+ hwnd = GetAuthWnd(&pi_access);
+ if (!hwnd || !pi_access) {
+ CHK_RELEASE(pi_access);
+ return false;
+ }
+ return true;
+}
+
+bool CTabImpl::SetAuthDialog(const BSTR user_name, const BSTR password) {
+ IAccessible *pi_access = NULL;
+ HWND hwnd = GetChromeBrowserWnd(&pi_access);
+ if (!pi_access || !hwnd)
+ return false;
+
+ // Activate main window.
+ ActivateWnd(pi_access, hwnd);
+ CHK_RELEASE(pi_access);
+
+ // Get editbox for user name and password.
+ pi_access = NULL;
+ hwnd = GetAuthWnd(&pi_access);
+ if (!hwnd) {
+ CHK_RELEASE(pi_access);
+ return false;
+ }
+
+ // Get handle to password edit box.
+ HWND hwnd_auth_pwd = FindWindowEx(hwnd, 0, CHROME_VIEWS_TEXT_FIELD_EDIT, 0);
+ if (!hwnd_auth_pwd) {
+ CHK_RELEASE(pi_access);
+ return false;
+ }
+
+ // Child after password edit box is edit box for name.
+ HWND hwnd_auth_name = FindWindowEx(hwnd, hwnd_auth_pwd,
+ CHROME_VIEWS_TEXT_FIELD_EDIT, 0);
+ if (!hwnd_auth_name) {
+ CHK_RELEASE(pi_access);
+ return false;
+ }
+
+ // Activate Tab.
+ SetActiveWindow(GetParent(hwnd));
+ // Activate Authentication window.
+ ActivateWnd(pi_access, hwnd);
+
+ // Activate edit box for name.
+ ActivateWnd(NULL, hwnd_auth_name);
+
+ // Set user name.
+ if (user_name != NULL) {
+ WCHAR* strTemp =
+ reinterpret_cast<WCHAR*>(calloc(wcslen(user_name), sizeof(WCHAR)));
+ wcscpy_s(strTemp, wcslen(user_name), user_name);
+ for (size_t i = 0; i < wcslen(strTemp); i++) {
+ SendMessage(hwnd_auth_name, WM_KEYDOWN, strTemp[i], 0);
+ SendMessage(hwnd_auth_name, WM_CHAR, strTemp[i], 0);
+ SendMessage(hwnd_auth_name, WM_KEYUP, strTemp[i], 0);
+ }
+ }
+
+ // Activate edit box for password.
+ ActivateWnd(NULL, hwnd_auth_pwd);
+
+ // Set password.
+ if (password != NULL) {
+ // set text
+ WCHAR* strTemp =
+ reinterpret_cast<WCHAR*>(calloc(wcslen(password), sizeof(WCHAR)));
+ wcscpy_s(strTemp, wcslen(password), password);
+ for (size_t i = 0; i < wcslen(strTemp); i++) {
+ SendMessage(hwnd_auth_pwd, WM_KEYDOWN, strTemp[i], 0);
+ SendMessage(hwnd_auth_pwd, WM_CHAR, strTemp[i], 0);
+ SendMessage(hwnd_auth_pwd, WM_KEYUP, strTemp[i], 0);
+ }
+ }
+
+ CHK_RELEASE(pi_access);
+ return true;
+}
+
+bool CTabImpl::CancelAuthDialog(void) {
+ IAccessible *pi_access = NULL;
+ HWND hwnd = GetChromeBrowserWnd(&pi_access);
+ if (!pi_access || !hwnd)
+ return false;
+
+ // Activate main window.
+ ActivateWnd(pi_access, hwnd);
+ CHK_RELEASE(pi_access);
+
+ // Get editbox for user name which is after password.
+ pi_access = NULL;
+ hwnd = GetAuthWnd(&pi_access);
+ if (!hwnd) {
+ CHK_RELEASE(pi_access);
+ return false;
+ }
+
+ // Get Cancel button.
+ HWND cancel_button_container =
+ FindWindowEx(hwnd, 0, CHROME_VIEWS_NATIVE_CTRL_CONTNR, 0);
+ if (!cancel_button_container) {
+ CHK_RELEASE(pi_access);
+ return false;
+ }
+ HWND cancel_button = FindWindowEx(cancel_button_container, 0, STD_BUTTON, 0);
+ if (!cancel_button) {
+ CHK_RELEASE(pi_access);
+ return false;
+ }
+
+ // Click Cancel button.
+ SetActiveWindow(cancel_button_container);
+ SetActiveWindow(cancel_button);
+ SendMessage(cancel_button, BM_CLICK, 0, 0);
+
+ return true;
+}
+
+bool CTabImpl::UseAuthDialog(void) {
+ IAccessible *pi_access = NULL;
+ HWND hwnd = GetChromeBrowserWnd(&pi_access);
+ if (!pi_access || !hwnd)
+ return false;
+
+ // Activate main window.
+ ActivateWnd(pi_access, hwnd);
+ CHK_RELEASE(pi_access);
+
+ // Get editbox for user name which is after password.
+ pi_access = NULL;
+ hwnd = GetAuthWnd(&pi_access);
+ if (!hwnd) {
+ CHK_RELEASE(pi_access);
+ return false;
+ }
+
+ // Get Ok button.
+ HWND cancel_button_container =
+ FindWindowEx(hwnd, 0, CHROME_VIEWS_NATIVE_CTRL_CONTNR, 0);
+ if (!cancel_button_container) {
+ CHK_RELEASE(pi_access);
+ return false;
+ }
+
+ // Ok button is located after cancel button in window hierarchy.
+ HWND ok_button_container = FindWindowEx(hwnd, cancel_button_container,
+ CHROME_VIEWS_NATIVE_CTRL_CONTNR, 0);
+ if (!ok_button_container) {
+ CHK_RELEASE(pi_access);
+ return false;
+ }
+ HWND ok_button = FindWindowEx(ok_button_container, 0, STD_BUTTON, 0);
+ if (!ok_button) {
+ CHK_RELEASE(pi_access);
+ return false;
+ }
+
+ // Click Ok.
+ SetActiveWindow(ok_button_container);
+ SetActiveWindow(ok_button);
+ SendMessage(ok_button, BM_CLICK, 0, 0);
+
+ return true;
+}
+
+bool CTabImpl::Activate(void) {
+ // TODO: Add your implementation code here
+
+ return true;
+}
+
+bool CTabImpl::WaitForTabToBecomeActive(const INT64 interval,
+ const INT64 timeout) {
+ // TODO: Add your implementation code here
+
+ return true;
+}
+
+bool CTabImpl::WaitForTabToGetLoaded(const INT64 interval,
+ const INT64 timeout) {
+ // TODO: Add your implementation code here
+
+ return true;
+}
+
+bool CTabImpl::IsSSLLockPresent(bool* present) {
+ // TODO: Add your implementation code here
+
+ return true;
+}
+
+bool CTabImpl::IsSSLSoftError(bool* soft_err) {
+ // TODO: Add your implementation code here
+
+ return true;
+}
+
+bool CTabImpl::OpenPageCertificateDialog(void) {
+ // TODO: Add your implementation code here
+
+ return true;
+}
+
+bool CTabImpl::ClosePageCertificateDialog(void) {
+ // TODO: Add your implementation code here
+
+ return true;
+}
+
+bool CTabImpl::GoBack(void) {
+ // TODO: Add your implementation code here
+
+ return true;
+}
+
+bool CTabImpl::GoForward(void) {
+ // TODO: Add your implementation code here
+
+ return true;
+}
diff --git a/chrome/test/accessibility/tab_impl.h b/chrome/test/accessibility/tab_impl.h
new file mode 100644
index 0000000..8bc5773
--- /dev/null
+++ b/chrome/test/accessibility/tab_impl.h
@@ -0,0 +1,163 @@
+// 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.
+
+#ifndef CHROME_TEST_ACCISSIBILITY_TAB_IMPL_H__
+#define CHROME_TEST_ACCISSIBILITY_TAB_IMPL_H__
+
+#include "constants.h"
+
+#include <oleauto.h>
+
+/////////////////////////////////////////////////////////////////////
+// CTabImpl
+// It is a wrapper to Tab specific functionalities.
+// Note:
+// In most of the tasks, keyboard messages are used for now.
+// DoDefaultAction() will be called on accessibility objects,
+// once implementation is available in chrome accessibility server.
+// And keyboard messages will be tested using ApplyAccelerator().
+/////////////////////////////////////////////////////////////////////
+
+// Forward declaration.
+class CBrowserImpl;
+
+// Structure storing Tab parameters.
+struct ChromeTab {
+ INT64 index_;
+ BSTR title_;
+};
+
+class CTabImpl {
+ public:
+ CTabImpl(): tab_(NULL), my_browser_(NULL) {
+ }
+
+ public:
+ // Close this tab.
+ bool Close(void);
+
+ // Returns title of this tab.
+ bool GetTitle(BSTR* title);
+
+ // Sets the URL in address bar.
+ bool SetAddressBarText(const BSTR text);
+
+ // Sets the URL and navigates tab to the page.
+ bool NavigateToURL(const BSTR url);
+
+ // Find string by invoking Find Window.
+ bool FindInPage(const BSTR find_text);
+
+ // Reloads/Refreshes the tab-page.
+ bool Reload(void);
+
+ // Duplicates this tab.
+ bool Duplicate(CTabImpl** tab);
+
+ // Returns true of Authentication dialog is opena nd visible.
+ bool IsAuthDialogVisible();
+
+ // Invokes authentication dialog with specified user name and password.
+ bool SetAuthDialog(const BSTR user_name, const BSTR password);
+
+ // Cancels invoked authentication dialog.
+ bool CancelAuthDialog(void);
+
+ // Authenticates with the credentials set in authentication dialog and
+ // closes it.
+ bool UseAuthDialog(void);
+
+ // Activates this tab.
+ bool Activate(void);
+
+ // Waits for specified time with the specified interval to get the tab
+ // activated.
+ bool WaitForTabToBecomeActive(const INT64 interval, const INT64 timeout);
+
+ // Waits for specified time with the specified interval to get the tab-page
+ // loaded with URL.
+ bool WaitForTabToGetLoaded(const INT64 interval, const INT64 timeout);
+
+ // Sets index of this tab.
+ void PutIndex(INT64 index) {
+ if (index < 0)
+ return;
+ if (!tab_)
+ InitTabData();
+ tab_->index_ = index;
+ }
+
+ // Sets title of this tab.
+ void PutTitle(BSTR title) {
+ if (!tab_)
+ InitTabData();
+ tab_->title_ = SysAllocString(title);
+ }
+
+ // Sets browser to which tab belongs.
+ bool SetBrowser(CBrowserImpl *browser) {
+ if (browser)
+ my_browser_ = browser;
+ else
+ return false;
+
+ return true;
+ }
+
+ // Initialize data specific to tab.
+ ChromeTab* InitTabData() {
+ if (tab_)
+ CHK_DELETE(tab_);
+
+ tab_ = new ChromeTab();
+ if (!tab_)
+ return NULL;
+
+ memset(tab_, 0, sizeof(ChromeTab));
+ return tab_;
+ }
+
+ // TODO
+ bool IsSSLLockPresent(bool* present);
+ bool IsSSLSoftError(bool* soft_err);
+ bool OpenPageCertificateDialog(void);
+ bool ClosePageCertificateDialog(void);
+ bool GoBack(void);
+ bool GoForward(void);
+
+ private:
+ // Structure to store tab data.
+ ChromeTab *tab_;
+
+ // Pointer to browser to which this tab belongs.
+ CBrowserImpl *my_browser_;
+};
+
+
+#endif // CHROME_TEST_ACCISSIBILITY_TAB_IMPL_H__
diff --git a/chrome/test/activex_test_control/SConscript b/chrome/test/activex_test_control/SConscript
new file mode 100644
index 0000000..6f459c1
--- /dev/null
+++ b/chrome/test/activex_test_control/SConscript
@@ -0,0 +1,93 @@
+# 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.
+
+Import('env')
+
+env = env.Clone()
+
+
+env.Prepend(
+ CPPPATH = [
+ '.',
+ '#/..',
+ ],
+ LINKFLAGS = [
+ '/INCREMENTAL',
+
+ '/MANIFEST',
+ '/DELAYLOAD:"dwmapi.dll"',
+ '/DELAYLOAD:"uxtheme.dll"',
+ '/MACHINE:X86',
+ '/FIXED:No',
+
+ '/safeseh',
+ '/dynamicbase',
+ '/ignore:4199',
+ '/nxcompat',
+
+ '/DEBUG',
+ ],
+ LIBS = [
+ 'wininet.lib',
+ 'version.lib',
+ 'msimg32.lib',
+ 'ws2_32.lib',
+ 'usp10.lib',
+ 'psapi.lib',
+ 'comsuppw.lib',
+ 'kernel32.lib',
+ 'user32.lib',
+ 'gdi32.lib',
+ 'winspool.lib',
+ 'comdlg32.lib',
+ 'advapi32.lib',
+ 'shell32.lib',
+ 'ole32.lib',
+ 'oleaut32.lib',
+ 'uuid.lib',
+ 'odbc32.lib',
+ 'odbccp32.lib',
+
+ 'DelayImp.lib',
+ ],
+)
+
+env.TypeLibrary('activex_test_control.idl')
+
+input_files = [
+ 'activex_test_control.cc',
+ 'activex_test_control.def',
+ 'chrome_test_control.cc',
+]
+
+dll = env.SharedLibrary(['activex_test_control', 'activex_test_control.lib'],
+ input_files)
+
+i = env.Install('$TARGET_ROOT', dll)
+env.Alias('chrome', i)
diff --git a/chrome/test/activex_test_control/activex_test_control.cc b/chrome/test/activex_test_control/activex_test_control.cc
new file mode 100644
index 0000000..829cb9a
--- /dev/null
+++ b/chrome/test/activex_test_control/activex_test_control.cc
@@ -0,0 +1,74 @@
+// 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.
+
+#include <atlbase.h>
+#include <atlcom.h>
+
+#include "activex_test_control.h"
+#include "activex_test_control_i.c"
+#include "chrome/test/activex_test_control/resource.h"
+
+class ActiveXTestControllModule
+ : public CAtlDllModuleT<ActiveXTestControllModule> {
+ public:
+ DECLARE_LIBID(LIBID_activex_test_controlLib)
+ DECLARE_REGISTRY_APPID_RESOURCEID(IDR_ACTIVEX_TEST_CONTROL,
+ "{CDBC0D94-AFF6-4918-90A9-7967179A77D8}")
+};
+
+ActiveXTestControllModule g_atlmodule;
+
+// DLL Entry Point
+extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason,
+ LPVOID reserved) {
+ return g_atlmodule.DllMain(reason, reserved);
+}
+
+// Used to determine whether the DLL can be unloaded by OLE
+STDAPI DllCanUnloadNow(void) {
+ return g_atlmodule.DllCanUnloadNow();
+}
+
+// Returns a class factory to create an object of the requested type
+STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv) {
+ return g_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 = g_atlmodule.DllRegisterServer();
+ return hr;
+}
+
+// DllUnregisterServer - Removes entries from the system registry
+STDAPI DllUnregisterServer(void) {
+ HRESULT hr = g_atlmodule.DllUnregisterServer();
+ return hr;
+}
diff --git a/chrome/test/activex_test_control/activex_test_control.def b/chrome/test/activex_test_control/activex_test_control.def
new file mode 100644
index 0000000..b006b57
--- /dev/null
+++ b/chrome/test/activex_test_control/activex_test_control.def
@@ -0,0 +1,9 @@
+; activex_test_control.def : Declares the module parameters.
+
+LIBRARY "activex_test_control.DLL"
+
+EXPORTS
+ DllCanUnloadNow PRIVATE
+ DllGetClassObject PRIVATE
+ DllRegisterServer PRIVATE
+ DllUnregisterServer PRIVATE
diff --git a/chrome/test/activex_test_control/activex_test_control.idl b/chrome/test/activex_test_control/activex_test_control.idl
new file mode 100644
index 0000000..04a2f42
--- /dev/null
+++ b/chrome/test/activex_test_control/activex_test_control.idl
@@ -0,0 +1,108 @@
+// 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.
+
+// This file will be processed by the MIDL tool to
+// produce the type library (activex_test_control.tlb) and marshalling code.
+
+#include "olectl.h"
+import "oaidl.idl";
+import "ocidl.idl";
+
+[
+ object,
+ uuid(9AC37249-E247-4B82-AC1E-0917737528E9),
+ dual,
+ nonextensible,
+ helpstring("IChromeTestControl Interface"),
+ pointer_default(unique)
+]
+interface IChromeTestControl : IDispatch{
+ [propput, bindable, requestedit, id(DISPID_BACKCOLOR)]
+ HRESULT BackColor([in]OLE_COLOR clr);
+ [propget, bindable, requestedit, id(DISPID_BACKCOLOR)]
+ HRESULT BackColor([out,retval]OLE_COLOR* pclr);
+ [propput, bindable, requestedit, id(DISPID_BORDERCOLOR)]
+ HRESULT BorderColor([in]OLE_COLOR clr);
+ [propget, bindable, requestedit, id(DISPID_BORDERCOLOR)]
+ HRESULT BorderColor([out, retval]OLE_COLOR* pclr);
+ [propput, bindable, requestedit, id(DISPID_FORECOLOR)]
+ HRESULT ForeColor([in]OLE_COLOR clr);
+ [propget, bindable, requestedit, id(DISPID_FORECOLOR)]
+ HRESULT ForeColor([out,retval]OLE_COLOR* pclr);
+ [propput, bindable, requestedit, id(DISPID_CAPTION)]
+ HRESULT Caption([in]BSTR strCaption);
+ [propget, bindable, requestedit, id(DISPID_CAPTION)]
+ HRESULT Caption([out,retval]BSTR* pstrCaption);
+ [propget, id(1), helpstring("property StringProp")] HRESULT StringProp([out, retval] BSTR* pVal);
+ [propput, id(1), helpstring("property StringProp")] HRESULT StringProp([in] BSTR newVal);
+ [propget, id(2), helpstring("property LongProp")] HRESULT LongProp([out, retval] LONG* pVal);
+ [propput, id(2), helpstring("property LongProp")] HRESULT LongProp([in] LONG newVal);
+ [propget, id(3), helpstring("property DoubleProp")] HRESULT DoubleProp([out, retval] DOUBLE* pVal);
+ [propput, id(3), helpstring("property DoubleProp")] HRESULT DoubleProp([in] DOUBLE newVal);
+ [propget, id(4), helpstring("property BoolProp")] HRESULT BoolProp([out, retval] VARIANT_BOOL* pVal);
+ [propput, id(4), helpstring("property BoolProp")] HRESULT BoolProp([in] VARIANT_BOOL newVal);
+ [propget, id(5), helpstring("property ByteProp")] HRESULT ByteProp([out, retval] BYTE* pVal);
+ [propput, id(5), helpstring("property ByteProp")] HRESULT ByteProp([in] BYTE newVal);
+ [propget, id(6), helpstring("property FloatProp")] HRESULT FloatProp([out, retval] FLOAT* pVal);
+ [propput, id(6), helpstring("property FloatProp")] HRESULT FloatProp([in] FLOAT newVal);
+ [id(7), helpstring("method BigSetMethod")] HRESULT BigSetMethodRet([in] BSTR string_param, [in] BYTE byte_param, [in] FLOAT float_param, [in] VARIANT_BOOL bool_param, [out,retval] BSTR* ret);
+ [id(8), helpstring("method SetByte")] HRESULT SetByte([in] BYTE val);
+ [id(9), helpstring("method SetByteRet")] HRESULT SetByteRet([in] BYTE byte_param, [out,retval] BYTE* ret);
+ [id(10), helpstring("method SetStringRet")] HRESULT SetStringRet([in] BSTR val, [out,retval] BSTR* ret);
+ [id(11), helpstring("method GetCookie")] HRESULT GetCookie([out,retval] BSTR* cookie);
+};
+
+[
+ uuid(83D767F4-5C4F-4ACA-B0E8-928C54845C33),
+ version(1.0),
+ helpstring("activex_test_control 1.0 Type Library")
+]
+library activex_test_controlLib
+{
+ importlib("stdole2.tlb");
+ [
+ uuid(EF88DE01-35AF-463F-9802-1BF908F48696),
+ helpstring("_IChromeTestControlEvents Interface")
+ ]
+ dispinterface _IChromeTestControlEvents
+ {
+ properties:
+ methods:
+ };
+ [
+ uuid(4E174456-5EE6-494D-B6F2-2B52898A620E),
+ control,
+ helpstring("ChromeTestControl Class")
+ ]
+ coclass ChromeTestControl
+ {
+ [default] interface IChromeTestControl;
+ [default, source] dispinterface _IChromeTestControlEvents;
+ };
+};
diff --git a/chrome/test/activex_test_control/activex_test_control.rc b/chrome/test/activex_test_control/activex_test_control.rc
new file mode 100644
index 0000000..e6046bd
--- /dev/null
+++ b/chrome/test/activex_test_control/activex_test_control.rc
@@ -0,0 +1,128 @@
+// 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 ""activex_test_control.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 Inc."
+ VALUE "FileDescription", "ActiveX Test Control"
+ VALUE "FileVersion", "1.0.0.1"
+ VALUE "LegalCopyright", "Google Inc. All rights reserved."
+ VALUE "InternalName", "activex_test_control.dll"
+ VALUE "OriginalFilename", "activex_test_control.dll"
+ VALUE "ProductName", "Google Chrome"
+ VALUE "ProductVersion", "1.0.0.1"
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x409, 1252
+ END
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// REGISTRY
+//
+
+IDR_ACTIVEX_TEST_CONTROL REGISTRY "activex_test_control.rgs"
+IDR_CHROMETESTCONTROL REGISTRY "chrome_test_control.rgs"
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Bitmap
+//
+
+IDB_CHROMETESTCONTROL BITMAP "chrome_test_control.bmp"
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// String Table
+//
+
+STRINGTABLE
+BEGIN
+ IDS_PROJNAME "activex_test_control"
+END
+
+#endif // English (U.S.) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+1 TYPELIB "activex_test_control.tlb"
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/chrome/test/activex_test_control/activex_test_control.rgs b/chrome/test/activex_test_control/activex_test_control.rgs
new file mode 100644
index 0000000..2873a48
--- /dev/null
+++ b/chrome/test/activex_test_control/activex_test_control.rgs
@@ -0,0 +1,11 @@
+HKCR
+{
+ NoRemove AppID
+ {
+ '%APPID%' = s 'activex_test_control'
+ 'activex_test_control.DLL'
+ {
+ val AppID = s '%APPID%'
+ }
+ }
+}
diff --git a/chrome/test/activex_test_control/activex_test_control.vcproj b/chrome/test/activex_test_control/activex_test_control.vcproj
new file mode 100644
index 0000000..b40d9b3e
--- /dev/null
+++ b/chrome/test/activex_test_control/activex_test_control.vcproj
@@ -0,0 +1,193 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="activex_test_control"
+ ProjectGUID="{414D4D24-5D65-498B-A33F-3A29AD3CDEDC}"
+ RootNamespace="activex_test_control"
+ Keyword="AtlProj"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ ConfigurationType="2"
+ InheritedPropertySheets=".\activex_test_control.vsprops;$(SolutionDir)..\build\debug.vsprops"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ />
+ <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"
+ ConfigurationType="2"
+ InheritedPropertySheets=".\activex_test_control.vsprops;$(SolutionDir)..\build\release.vsprops"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ />
+ <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="resource"
+ >
+ <File
+ RelativePath=".\activex_test_control.rc"
+ >
+ </File>
+ <File
+ RelativePath=".\activex_test_control.rgs"
+ >
+ </File>
+ <File
+ RelativePath=".\chrome_test_control.bmp"
+ >
+ </File>
+ <File
+ RelativePath=".\chrome_test_control.rgs"
+ >
+ </File>
+ </Filter>
+ <File
+ RelativePath=".\activex_test_control.cc"
+ >
+ </File>
+ <File
+ RelativePath=".\activex_test_control.def"
+ >
+ </File>
+ <File
+ RelativePath=".\activex_test_control.idl"
+ >
+ </File>
+ <File
+ RelativePath=".\chrome_test_control.cc"
+ >
+ </File>
+ <File
+ RelativePath=".\chrome_test_control.h"
+ >
+ </File>
+ <File
+ RelativePath=".\chrome_test_control_cp.h"
+ >
+ </File>
+ <File
+ RelativePath=".\resource.h"
+ >
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/chrome/test/activex_test_control/activex_test_control.vsprops b/chrome/test/activex_test_control/activex_test_control.vsprops
new file mode 100644
index 0000000..d873ddf
--- /dev/null
+++ b/chrome/test/activex_test_control/activex_test_control.vsprops
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioPropertySheet
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="activex_test_control"
+ InheritedPropertySheets="$(SolutionDir)..\build\common.vsprops"
+ UseOfATL="1"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="$(IntDir)"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ RegisterOutput="false"
+ IgnoreImportLibrary="true"
+ AdditionalDependencies="comsuppw.lib"
+ OutputFile="$(OutDir)\activex_test_control.dll"
+ ModuleDefinitionFile=".\activex_test_control.def"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ AdditionalIncludeDirectories="$(IntDir)"
+ />
+</VisualStudioPropertySheet>
diff --git a/chrome/test/activex_test_control/chrome_test_control.bmp b/chrome/test/activex_test_control/chrome_test_control.bmp
new file mode 100644
index 0000000..1229764
--- /dev/null
+++ b/chrome/test/activex_test_control/chrome_test_control.bmp
Binary files differ
diff --git a/chrome/test/activex_test_control/chrome_test_control.cc b/chrome/test/activex_test_control/chrome_test_control.cc
new file mode 100644
index 0000000..5b0655c
--- /dev/null
+++ b/chrome/test/activex_test_control/chrome_test_control.cc
@@ -0,0 +1,59 @@
+// 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.
+
+#include "chrome/test/activex_test_control/chrome_test_control.h"
+
+// CChromeTestControl
+HRESULT ChromeTestControl::OnDraw(ATL_DRAWINFO& di) {
+ RECT& rc = *(RECT*)di.prcBounds;
+ // Set Clip region to the rectangle specified by di.prcBounds
+ HRGN rgn_old = NULL;
+ if (GetClipRgn(di.hdcDraw, rgn_old) != 1)
+ rgn_old = NULL;
+ bool select_old_rgn = false;
+
+ HRGN rgn_new = CreateRectRgn(rc.left, rc.top, rc.right, rc.bottom);
+
+ if (rgn_new != NULL)
+ select_old_rgn = (SelectClipRgn(di.hdcDraw, rgn_new) != ERROR);
+
+ Rectangle(di.hdcDraw, rc.left, rc.top, rc.right, rc.bottom);
+ SetTextAlign(di.hdcDraw, TA_CENTER|TA_BASELINE);
+ LPCTSTR pszText = _T("ATL 8.0 : ChromeTestControl");
+ TextOut(di.hdcDraw,
+ (rc.left + rc.right) / 2,
+ (rc.top + rc.bottom) / 2,
+ pszText,
+ lstrlen(pszText));
+
+ if (select_old_rgn)
+ SelectClipRgn(di.hdcDraw, rgn_old);
+
+ return S_OK;
+}
diff --git a/chrome/test/activex_test_control/chrome_test_control.h b/chrome/test/activex_test_control/chrome_test_control.h
new file mode 100644
index 0000000..e923307
--- /dev/null
+++ b/chrome/test/activex_test_control/chrome_test_control.h
@@ -0,0 +1,286 @@
+// 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.
+
+#ifndef CHROME_TEST_ACTIVEX_TEST_CONTROL_CHROME_TEST_CONTROL_H__
+#define CHROME_TEST_ACTIVEX_TEST_CONTROL_CHROME_TEST_CONTROL_H__
+
+#include <atlbase.h>
+#include <atlcom.h>
+#include <atlctl.h>
+#include <comutil.h>
+#include "activex_test_control.h"
+#include "chrome/test/activex_test_control/chrome_test_control_cp.h"
+#include "chrome/test/activex_test_control/resource.h"
+
+// ChromeTestControl
+class ATL_NO_VTABLE ChromeTestControl
+ : public CComObjectRootEx<CComSingleThreadModel>,
+ public CStockPropImpl<ChromeTestControl, IChromeTestControl>,
+ public IPersistStreamInitImpl<ChromeTestControl>,
+ public IOleControlImpl<ChromeTestControl>,
+ public IOleObjectImpl<ChromeTestControl>,
+ public IOleInPlaceActiveObjectImpl<ChromeTestControl>,
+ public IViewObjectExImpl<ChromeTestControl>,
+ public IOleInPlaceObjectWindowlessImpl<ChromeTestControl>,
+ public ISupportErrorInfo,
+ public IConnectionPointContainerImpl<ChromeTestControl>,
+ public CProxy_IChromeTestControlEvents<ChromeTestControl>,
+ public IObjectWithSiteImpl<ChromeTestControl>,
+ public IServiceProviderImpl<ChromeTestControl>,
+ public IPersistStorageImpl<ChromeTestControl>,
+ public ISpecifyPropertyPagesImpl<ChromeTestControl>,
+ public IQuickActivateImpl<ChromeTestControl>,
+ public IDataObjectImpl<ChromeTestControl>,
+ public IProvideClassInfo2Impl<&CLSID_ChromeTestControl,
+ &__uuidof(_IChromeTestControlEvents), &LIBID_activex_test_controlLib>,
+ public IPropertyNotifySinkCP<ChromeTestControl>,
+ public IObjectSafetyImpl<ChromeTestControl,
+ INTERFACESAFE_FOR_UNTRUSTED_CALLER |
+ INTERFACESAFE_FOR_UNTRUSTED_DATA>,
+ public CComCoClass<ChromeTestControl, &CLSID_ChromeTestControl>,
+ public CComControl<ChromeTestControl> {
+ public:
+ ChromeTestControl() {
+ }
+
+DECLARE_OLEMISC_STATUS(OLEMISC_RECOMPOSEONRESIZE |
+ OLEMISC_CANTLINKINSIDE |
+ OLEMISC_INSIDEOUT |
+ OLEMISC_ACTIVATEWHENVISIBLE |
+ OLEMISC_SETCLIENTSITEFIRST)
+
+DECLARE_REGISTRY_RESOURCEID(IDR_CHROMETESTCONTROL)
+
+BEGIN_COM_MAP(ChromeTestControl)
+ COM_INTERFACE_ENTRY(IChromeTestControl)
+ COM_INTERFACE_ENTRY(IDispatch)
+ COM_INTERFACE_ENTRY(IViewObjectEx)
+ COM_INTERFACE_ENTRY(IViewObject2)
+ COM_INTERFACE_ENTRY(IViewObject)
+ COM_INTERFACE_ENTRY(IOleInPlaceObjectWindowless)
+ COM_INTERFACE_ENTRY(IOleInPlaceObject)
+ COM_INTERFACE_ENTRY2(IOleWindow, IOleInPlaceObjectWindowless)
+ COM_INTERFACE_ENTRY(IOleInPlaceActiveObject)
+ COM_INTERFACE_ENTRY(IOleControl)
+ COM_INTERFACE_ENTRY(IOleObject)
+ COM_INTERFACE_ENTRY(IPersistStreamInit)
+ COM_INTERFACE_ENTRY2(IPersist, IPersistStreamInit)
+ COM_INTERFACE_ENTRY(ISupportErrorInfo)
+ COM_INTERFACE_ENTRY(IConnectionPointContainer)
+ COM_INTERFACE_ENTRY(ISpecifyPropertyPages)
+ COM_INTERFACE_ENTRY(IQuickActivate)
+ COM_INTERFACE_ENTRY(IPersistStorage)
+ COM_INTERFACE_ENTRY(IDataObject)
+ COM_INTERFACE_ENTRY(IProvideClassInfo)
+ COM_INTERFACE_ENTRY(IProvideClassInfo2)
+ COM_INTERFACE_ENTRY(IObjectWithSite)
+ COM_INTERFACE_ENTRY(IServiceProvider)
+ COM_INTERFACE_ENTRY_IID(IID_IObjectSafety, IObjectSafety)
+END_COM_MAP()
+
+BEGIN_PROP_MAP(ChromeTestControl)
+ PROP_DATA_ENTRY("_cx", m_sizeExtent.cx, VT_UI4)
+ PROP_DATA_ENTRY("_cy", m_sizeExtent.cy, VT_UI4)
+ PROP_ENTRY("BackColor", DISPID_BACKCOLOR, CLSID_StockColorPage)
+ PROP_ENTRY("BorderColor", DISPID_BORDERCOLOR, CLSID_StockColorPage)
+ PROP_ENTRY("Caption", DISPID_CAPTION, CLSID_NULL)
+ PROP_ENTRY("ForeColor", DISPID_FORECOLOR, CLSID_StockColorPage)
+ // Example entries
+ // PROP_ENTRY("Property Description", dispid, clsid)
+ // PROP_PAGE(CLSID_StockColorPage)
+END_PROP_MAP()
+
+BEGIN_CONNECTION_POINT_MAP(ChromeTestControl)
+ CONNECTION_POINT_ENTRY(IID_IPropertyNotifySink)
+ CONNECTION_POINT_ENTRY(__uuidof(_IChromeTestControlEvents))
+END_CONNECTION_POINT_MAP()
+
+BEGIN_MSG_MAP(ChromeTestControl)
+ CHAIN_MSG_MAP(CComControl<ChromeTestControl>)
+ DEFAULT_REFLECTION_HANDLER()
+END_MSG_MAP()
+
+ // ISupportsErrorInfo
+ STDMETHOD(InterfaceSupportsErrorInfo)(REFIID riid) {
+ static const IID* arr[] = {
+ &IID_IChromeTestControl,
+ };
+
+ for (int i=0; i<sizeof(arr)/sizeof(arr[0]); i++) {
+ if (InlineIsEqualGUID(*arr[i], riid))
+ return S_OK;
+ }
+ return S_FALSE;
+ }
+
+ // IViewObjectEx
+ DECLARE_VIEW_STATUS(VIEWSTATUS_SOLIDBKGND | VIEWSTATUS_OPAQUE)
+
+// IChromeTestControl
+ public:
+ HRESULT OnDraw(ATL_DRAWINFO& di);
+
+ void OnBackColorChanged() {
+ ATLTRACE(_T("OnBackColorChanged\n"));
+ }
+ void OnBorderColorChanged() {
+ ATLTRACE(_T("OnBorderColorChanged\n"));
+ }
+ void OnCaptionChanged() {
+ ATLTRACE(_T("OnCaptionChanged\n"));
+ }
+ void OnForeColorChanged() {
+ ATLTRACE(_T("OnForeColorChanged\n"));
+ }
+ STDMETHOD(_InternalQueryService)(REFGUID guidService, REFIID riid,
+ void** ppvObject) {
+ return E_NOTIMPL;
+ }
+
+ DECLARE_PROTECT_FINAL_CONSTRUCT()
+
+ HRESULT FinalConstruct() {
+ return S_OK;
+ }
+
+ void FinalRelease() {
+ }
+
+ STDMETHOD(get_StringProp)(BSTR* val) {
+ *val = string_prop_.copy();
+ return S_OK;
+ }
+
+ STDMETHOD(put_StringProp)(BSTR val) {
+ string_prop_ = val;
+ return S_OK;
+ }
+ STDMETHOD(get_LongProp)(LONG* val) {
+ *val = long_prop_;
+ return S_OK;
+ }
+
+ STDMETHOD(put_LongProp)(LONG val) {
+ long_prop_ = val;
+ return S_OK;
+ }
+ STDMETHOD(get_DoubleProp)(DOUBLE* val) {
+ *val = double_prop_;
+ return S_OK;
+ }
+
+ STDMETHOD(put_DoubleProp)(DOUBLE val) {
+ double_prop_ = val;
+ return S_OK;
+ }
+
+ STDMETHOD(get_BoolProp)(VARIANT_BOOL* val) {
+ *val = bool_prop_;
+ return S_OK;
+ }
+
+ STDMETHOD(put_BoolProp)(VARIANT_BOOL val) {
+ bool_prop_ = val;
+ return S_OK;
+ }
+
+ STDMETHOD(get_ByteProp)(BYTE* val) {
+ *val = byte_prop_;
+ return S_OK;
+ }
+
+ STDMETHOD(put_ByteProp)(BYTE val) {
+ byte_prop_ = val;
+ return S_OK;
+ }
+
+ STDMETHOD(get_FloatProp)(FLOAT* val) {
+ *val = float_prop_;
+ return S_OK;
+ }
+
+ STDMETHOD(put_FloatProp)(FLOAT val) {
+ float_prop_ = val;
+ return S_OK;
+ }
+
+ STDMETHOD(SetByte)(BYTE val) {
+ byte_prop_ = val;
+ return S_OK;
+ }
+ STDMETHOD(SetByteRet)(BYTE val, BYTE* ret) {
+ byte_prop_ = val;
+ *ret = val;
+ return S_OK;
+ }
+ STDMETHOD(SetStringRet)(BSTR val, BSTR* ret) {
+ string_prop_ = val;
+ *ret = string_prop_.copy();
+ return S_OK;
+ }
+ STDMETHOD(BigSetMethodRet)(BSTR string_param, BYTE byte_param,
+ FLOAT float_param, VARIANT_BOOL bool_param,
+ BSTR* ret) {
+ string_prop_ = string_param;
+ byte_prop_ = byte_param;
+ float_prop_ = float_param;
+ bool_prop_ = bool_param;
+ *ret = SysAllocString(string_param);
+ return S_OK;
+ }
+ STDMETHOD(GetCookie)(BSTR* cookie) {
+ CComPtr<IOleContainer> container;
+ m_spClientSite->GetContainer(&container);
+ CComQIPtr<IHTMLDocument2> doc = container;
+ if (doc == NULL) {
+ *cookie = SysAllocString(L"Bad");
+ return S_FALSE;
+ } else {
+ return doc->get_cookie(cookie);
+ }
+ }
+
+ // These varialbes are used by CStockPropImpl invisibly and they have to be
+ // be public to be accessible.
+ OLE_COLOR m_clrBackColor;
+ OLE_COLOR m_clrBorderColor;
+ CComBSTR m_bstrCaption;
+ OLE_COLOR m_clrForeColor;
+ private:
+ _bstr_t string_prop_;
+ LONG long_prop_;
+ DOUBLE double_prop_;
+ VARIANT_BOOL bool_prop_;
+ BYTE byte_prop_;
+ FLOAT float_prop_;
+};
+
+OBJECT_ENTRY_AUTO(__uuidof(ChromeTestControl), ChromeTestControl)
+
+#endif // #ifndef CHROME_TEST_ACTIVEX_TEST_CONTROL_CHROME_TEST_CONTROL_H__
diff --git a/chrome/test/activex_test_control/chrome_test_control.rgs b/chrome/test/activex_test_control/chrome_test_control.rgs
new file mode 100644
index 0000000..9e327bc
--- /dev/null
+++ b/chrome/test/activex_test_control/chrome_test_control.rgs
@@ -0,0 +1,34 @@
+HKCR
+{
+ activex_test_control.ChromeTestContro.1 = s 'ChromeTestControl Class'
+ {
+ CLSID = s '{4E174456-5EE6-494D-B6F2-2B52898A620E}'
+ }
+ activex_test_control.ChromeTestControl = s 'ChromeTestControl Class'
+ {
+ CLSID = s '{4E174456-5EE6-494D-B6F2-2B52898A620E}'
+ CurVer = s 'activex_test_control.ChromeTestContro.1'
+ }
+ NoRemove CLSID
+ {
+ ForceRemove {4E174456-5EE6-494D-B6F2-2B52898A620E} = s 'ChromeTestControl Class'
+ {
+ ProgID = s 'activex_test_control.ChromeTestContro.1'
+ VersionIndependentProgID = s 'activex_test_control.ChromeTestControl'
+ ForceRemove 'Programmable'
+ InprocServer32 = s '%MODULE%'
+ {
+ val ThreadingModel = s 'Apartment'
+ }
+ val AppID = s '%APPID%'
+ ForceRemove 'Control'
+ ForceRemove 'ToolboxBitmap32' = s '%MODULE%, 102'
+ 'MiscStatus' = s '0'
+ {
+ '1' = s '%OLEMISC%'
+ }
+ 'TypeLib' = s '{83D767F4-5C4F-4ACA-B0E8-928C54845C33}'
+ 'Version' = s '1.0'
+ }
+ }
+}
diff --git a/chrome/test/activex_test_control/chrome_test_control_cp.h b/chrome/test/activex_test_control/chrome_test_control_cp.h
new file mode 100644
index 0000000..734b326
--- /dev/null
+++ b/chrome/test/activex_test_control/chrome_test_control_cp.h
@@ -0,0 +1,42 @@
+// 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.
+
+#ifndef CHROME_TEST_ACTIVEX_TEST_CONTROL_CHROME_TEST_CONTROL_CP_H__
+#define CHROME_TEST_ACTIVEX_TEST_CONTROL_CHROME_TEST_CONTROL_CP_H__
+
+
+template <class T>
+class CProxy_IChromeTestControlEvents
+ : public IConnectionPointImpl<T, &__uuidof(_IChromeTestControlEvents),
+ CComDynamicUnkArray> {
+ //Warning this class will be regenerated by the wizard.
+ public:
+};
+
+#endif // #ifndef CHROME_TEST_ACTIVEX_TEST_CONTROL_CHROME_TEST_CONTROL_CP_H__
diff --git a/chrome/test/activex_test_control/resource.h b/chrome/test/activex_test_control/resource.h
new file mode 100644
index 0000000..fc3cd4e
--- /dev/null
+++ b/chrome/test/activex_test_control/resource.h
@@ -0,0 +1,19 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by activex_test_control.rc
+//
+#define IDS_PROJNAME 100
+#define IDR_ACTIVEX_TEST_CONTROL 101
+#define IDB_CHROMETESTCONTROL 102
+#define IDR_CHROMETESTCONTROL 103
+
+// 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 104
+#endif
+#endif
diff --git a/chrome/test/automated_ui_tests/automated_ui_tests.cc b/chrome/test/automated_ui_tests/automated_ui_tests.cc
new file mode 100644
index 0000000..0129e81
--- /dev/null
+++ b/chrome/test/automated_ui_tests/automated_ui_tests.cc
@@ -0,0 +1,887 @@
+// 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.
+
+#include <fstream>
+
+#include "base/command_line.h"
+#include "base/file_util.h"
+#include "base/path_service.h"
+#include "base/string_util.h"
+#include "chrome/app/chrome_dll_resource.h"
+#include "chrome/browser/view_ids.h"
+#include "chrome/common/chrome_paths.h"
+#include "chrome/common/libxml_utils.h"
+#include "chrome/common/rand_util.h"
+#include "chrome/common/win_util.h"
+#include "chrome/test/automated_ui_tests/automated_ui_tests.h"
+#include "chrome/test/automation/browser_proxy.h"
+#include "chrome/test/automation/tab_proxy.h"
+#include "chrome/test/automation/window_proxy.h"
+#include "chrome/test/ui/ui_test.h"
+#include "chrome/views/view.h"
+#include "googleurl/src/gurl.h"
+
+namespace {
+
+const wchar_t* const kReproSwitch = L"key";
+
+const wchar_t* const kReproRepeatSwitch = L"num-reproductions";
+
+const wchar_t* const kInputFilePathSwitch = L"input";
+
+const wchar_t* const kOutputFilePathSwitch = L"output";
+
+const wchar_t* const kDebugModeSwitch = L"debug";
+
+const wchar_t* const kDefaultInputFilePath = L"C:\\automated_ui_tests.txt";
+
+const wchar_t* const kDefaultOutputFilePath
+ = L"C:\\automated_ui_tests_error_report.txt";
+
+const int kDebuggingTimeoutMsec = 5000;
+
+// How many commands to run when testing a dialog box.
+const int kTestDialogActionsToRun = 7;
+
+} // namespace
+
+// This subset of commands is used to test dialog boxes, which aren't likely
+// to respond to most other commands.
+std::string AutomatedUITest::test_dialog_possible_actions_[] = {
+ "PressTabKey",
+ "PressEnterKey",
+ "PressSpaceBar",
+ "DownArrow"
+};
+
+AutomatedUITest::AutomatedUITest()
+ : total_crashes_(0),
+ debug_logging_enabled_(false) {
+ show_window_ = true;
+ GetSystemTimeAsFileTime(&test_start_time_);
+ CommandLine parsed_command_line;
+ if (parsed_command_line.HasSwitch(kDebugModeSwitch))
+ debug_logging_enabled_ = true;
+}
+
+AutomatedUITest::~AutomatedUITest() {}
+
+void AutomatedUITest::RunReproduction() {
+ CommandLine parsed_command_line;
+ xml_writer_.StartWriting();
+ xml_writer_.StartElement("Report");
+ std::string action_string =
+ WideToASCII(parsed_command_line.GetSwitchValue(kReproSwitch));
+
+ int64 num_reproductions = 1;
+ if (parsed_command_line.HasSwitch(kReproRepeatSwitch)) {
+ std::wstring num_reproductions_string =
+ parsed_command_line.GetSwitchValue(kReproRepeatSwitch);
+ std::string test = WideToASCII(num_reproductions_string);
+ num_reproductions = StringToInt64(num_reproductions_string);
+ }
+ std::vector<std::string> actions;
+ SplitString(action_string, L',', &actions);
+ bool did_crash = false;
+ bool command_complete = false;
+
+ for (int64 i = 0; i < num_reproductions && !did_crash; ++i) {
+ bool did_teardown = false;
+ xml_writer_.StartElement("Executed");
+ for (size_t j = 0; j < actions.size(); ++j) {
+ DoAction(actions[j]);
+ if (DidCrash(true)) {
+ did_crash = true;
+ if (j >= (actions.size() - 1))
+ command_complete = true;
+ break;
+ }
+ if (LowerCaseEqualsASCII(actions[j], "teardown"))
+ did_teardown = true;
+ }
+
+ // Force proper teardown after each run, if it didn't already happen. But
+ // don't teardown after crashes.
+ if (!did_teardown && !did_crash)
+ DoAction("TearDown");
+
+ xml_writer_.EndElement(); // End "Executed" element.
+ }
+
+ if (did_crash) {
+ std::string crash_dump = WideToASCII(GetMostRecentCrashDump());
+ std::string result =
+ "*** Crash dump produced. See result file for more details. Dump = ";
+ result.append(crash_dump);
+ result.append(" ***\n");
+ printf("%s", result.c_str());
+ LogCrashResult(crash_dump, command_complete);
+ EXPECT_TRUE(false) << "Crash detected.";
+ } else {
+ printf("*** No crashes. See result file for more details. ***\n");
+ LogSuccessResult();
+ }
+
+ WriteReportToFile();
+}
+
+
+void AutomatedUITest::RunAutomatedUITest() {
+ ASSERT_TRUE(InitXMLReader()) << "Error initializing XMLReader";
+ xml_writer_.StartWriting();
+ xml_writer_.StartElement("Report");
+
+ while (init_reader_.Read()) {
+ init_reader_.SkipToElement();
+ std::string node_name = init_reader_.NodeName();
+ if (LowerCaseEqualsASCII(node_name, "command")) {
+ bool no_errors = true;
+ xml_writer_.StartElement("Executed");
+ std::string command_number;
+ if (init_reader_.NodeAttribute("number", &command_number)) {
+ xml_writer_.AddAttribute("command_number", command_number);
+ }
+ xml_writer_.StopIndenting();
+
+ // Starts the browser, logging it as an action.
+ DoAction("SetUp");
+
+ // Record the depth of the root of the command subtree, then advance to
+ // the first element in preperation for parsing.
+ int start_depth = init_reader_.Depth();
+ ASSERT_TRUE(init_reader_.Read()) << "Malformed XML file.";
+ init_reader_.SkipToElement();
+
+ // Check for a crash right after startup.
+ if (DidCrash(true)) {
+ LogCrashResult(WideToASCII(GetMostRecentCrashDump()), false);
+ // Try and start up again.
+ CloseBrowserAndServer();
+ LaunchBrowserAndServer();
+ if (DidCrash(true)) {
+ no_errors = false;
+ // We crashed again, so skip to the end of the this command.
+ while (init_reader_.Depth() != start_depth) {
+ ASSERT_TRUE(init_reader_.Read()) << "Malformed XML file.";
+ }
+ } else {
+ // We didn't crash, so end the old element, logging a crash for that.
+ // Then start a new element to log this command.
+ xml_writer_.StartIndenting();
+ xml_writer_.EndElement();
+ xml_writer_.StartElement("Executed");
+ xml_writer_.AddAttribute("command_number", command_number);
+ xml_writer_.StopIndenting();
+ xml_writer_.StartElement("SetUp");
+ xml_writer_.EndElement();
+ }
+ }
+ // Parse the command, performing the specified actions and checking
+ // for a crash after each one.
+ while (init_reader_.Depth() != start_depth) {
+ node_name = init_reader_.NodeName();
+
+ DoAction(node_name);
+
+ // Advance to the next element
+ ASSERT_TRUE(init_reader_.Read()) << "Malformed XML file.";
+ init_reader_.SkipToElement();
+ if (DidCrash(true)) {
+ no_errors = false;
+ // This was the last action if we've returned to the initial depth
+ // of the command subtree.
+ bool wasLastAction = init_reader_.Depth() == start_depth;
+ LogCrashResult(WideToASCII(GetMostRecentCrashDump()), wasLastAction);
+ // Skip to the beginning of the next command.
+ while (init_reader_.Depth() != start_depth) {
+ ASSERT_TRUE(init_reader_.Read()) << "Malformed XML file.";
+ }
+ }
+ }
+
+ if (no_errors) {
+ // If there were no previous crashes, log our tear down and check for
+ // a crash, log success for the entire command if this doesn't crash.
+ DoAction("TearDown");
+ if (DidCrash(true))
+ LogCrashResult(WideToASCII(GetMostRecentCrashDump()), true);
+ else
+ LogSuccessResult();
+ } else {
+ // If there was a previous crash, just tear down without logging, so
+ // that we know what the last command was before we crashed.
+ CloseBrowserAndServer();
+ }
+
+ xml_writer_.StartIndenting();
+ xml_writer_.EndElement(); // End "Executed" element.
+ }
+ }
+ // The test is finished so write our report.
+ WriteReportToFile();
+}
+
+bool AutomatedUITest::DoAction(const std::string & action) {
+ bool did_complete_action = false;
+ xml_writer_.StartElement(action);
+ if (debug_logging_enabled_)
+ AppendToOutputFile(action);
+
+ if (LowerCaseEqualsASCII(action, "navigate")) {
+ did_complete_action = Navigate();
+ } else if (LowerCaseEqualsASCII(action, "newtab")) {
+ did_complete_action = NewTab();
+ } else if (LowerCaseEqualsASCII(action, "back")) {
+ did_complete_action = BackButton();
+ } else if (LowerCaseEqualsASCII(action, "forward")) {
+ did_complete_action = ForwardButton();
+ } else if (LowerCaseEqualsASCII(action, "closetab")) {
+ did_complete_action = CloseActiveTab();
+ } else if (LowerCaseEqualsASCII(action, "openwindow")) {
+ did_complete_action = OpenAndActivateNewBrowserWindow();
+ } else if (LowerCaseEqualsASCII(action, "reload")) {
+ did_complete_action = ReloadPage();
+ } else if (LowerCaseEqualsASCII(action, "star")) {
+ did_complete_action = StarPage();
+ } else if (LowerCaseEqualsASCII(action, "findinpage")) {
+ did_complete_action = FindInPage();
+ } else if (LowerCaseEqualsASCII(action, "selectnexttab")) {
+ did_complete_action = SelectNextTab();
+ } else if (LowerCaseEqualsASCII(action, "selectprevtab")) {
+ did_complete_action = SelectPreviousTab();
+ } else if (LowerCaseEqualsASCII(action, "zoomplus")) {
+ did_complete_action = ZoomPlus();
+ } else if (LowerCaseEqualsASCII(action, "zoomminus")) {
+ did_complete_action = ZoomMinus();
+ } else if (LowerCaseEqualsASCII(action, "history")) {
+ did_complete_action = ShowHistory();
+ } else if (LowerCaseEqualsASCII(action, "downloads")) {
+ did_complete_action = ShowDownloads();
+ } else if (LowerCaseEqualsASCII(action, "importsettings")) {
+ did_complete_action = ImportSettings();
+ } else if (LowerCaseEqualsASCII(action, "viewpasswords")) {
+ did_complete_action = ViewPasswords();
+ } else if (LowerCaseEqualsASCII(action, "clearbrowserdata")) {
+ did_complete_action = ClearBrowserData();
+ } else if (LowerCaseEqualsASCII(action, "taskmanager")) {
+ did_complete_action = TaskManager();
+ } else if (LowerCaseEqualsASCII(action, "goofftherecord")) {
+ did_complete_action = GoOffTheRecord();
+ } else if (LowerCaseEqualsASCII(action, "pressescapekey")) {
+ did_complete_action = PressEscapeKey();
+ } else if (LowerCaseEqualsASCII(action, "presstabkey")) {
+ did_complete_action = PressTabKey();
+ } else if (LowerCaseEqualsASCII(action, "pressenterkey")) {
+ did_complete_action = PressEnterKey();
+ } else if (LowerCaseEqualsASCII(action, "pressspacebar")) {
+ did_complete_action = PressSpaceBar();
+ } else if (LowerCaseEqualsASCII(action, "pagedown")) {
+ did_complete_action = PageDown();
+ } else if (LowerCaseEqualsASCII(action, "pageup")) {
+ did_complete_action = PageUp();
+ } else if (LowerCaseEqualsASCII(action, "dragtabright")) {
+ did_complete_action = DragActiveTab(true, false);
+ } else if (LowerCaseEqualsASCII(action, "dragtableft")) {
+ did_complete_action = DragActiveTab(false, false);
+ } else if (LowerCaseEqualsASCII(action, "dragtabout")) {
+ did_complete_action = DragActiveTab(false, true);
+ } else if (LowerCaseEqualsASCII(action, "uparrow")) {
+ did_complete_action = UpArrow();
+ } else if (LowerCaseEqualsASCII(action, "downarrow")) {
+ did_complete_action = DownArrow();
+ } else if (LowerCaseEqualsASCII(action, "testeditkeywords")) {
+ did_complete_action = TestEditKeywords();
+ } else if (LowerCaseEqualsASCII(action, "testtaskmanager")) {
+ did_complete_action = TestTaskManager();
+ } else if (LowerCaseEqualsASCII(action, "testviewpasswords")) {
+ did_complete_action = TestViewPasswords();
+ } else if (LowerCaseEqualsASCII(action, "testclearbrowserdata")) {
+ did_complete_action = TestClearBrowserData();
+ } else if (LowerCaseEqualsASCII(action, "testimportsettings")) {
+ did_complete_action = TestImportSettings();
+ } else if (LowerCaseEqualsASCII(action, "crash")) {
+ did_complete_action = ForceCrash();
+ } else if (LowerCaseEqualsASCII(action, "sleep")) {
+ // This is for debugging, it probably shouldn't be used real tests.
+ Sleep(kDebuggingTimeoutMsec);
+ did_complete_action = true;
+ } else if (LowerCaseEqualsASCII(action, "setup")) {
+ LaunchBrowserAndServer();
+ did_complete_action = true;
+ } else if (LowerCaseEqualsASCII(action, "teardown")) {
+ CloseBrowserAndServer();
+ did_complete_action = true;
+ }
+
+ if (!did_complete_action)
+ xml_writer_.AddAttribute("failed_to_complete", "yes");
+ xml_writer_.EndElement();
+
+ return did_complete_action;
+}
+
+bool AutomatedUITest::Navigate() {
+ scoped_ptr<BrowserProxy> browser(automation()->GetLastActiveBrowserWindow());
+ if (browser.get() == NULL) {
+ AddErrorAttribute("browser_window_not_found");
+ return false;
+ }
+ bool did_timeout;
+ scoped_ptr<TabProxy> tab(
+ browser->GetActiveTabWithTimeout(kWaitForActionMaxMsec, &did_timeout));
+ // TODO(devint): This might be masking a bug. I can't think of many
+ // valid cases where we would get a browser window, but not be able
+ // to return an active tab. Yet this has happened and has triggered crashes.
+ // Investigate this.
+ if (tab.get() == NULL) {
+ AddErrorAttribute("active_tab_not_found");
+ return false;
+ }
+ std::string url = "about:blank";
+ if (init_reader_.NodeAttribute("url", &url)) {
+ xml_writer_.AddAttribute("url", url);
+ }
+ GURL test_url(url);
+ did_timeout = false;
+ tab->NavigateToURLWithTimeout(test_url, kMaxTestExecutionTime, &did_timeout);
+
+ if (did_timeout) {
+ AddWarningAttribute("timeout");
+ return false;
+ }
+ return true;
+}
+
+bool AutomatedUITest::NewTab() {
+ scoped_ptr<BrowserProxy> browser(automation()->GetLastActiveBrowserWindow());
+ if (browser.get() == NULL) {
+ AddErrorAttribute("browser_window_not_found");
+ return false;
+ }
+ int old_tab_count;
+ int new_tab_count;
+ bool is_timeout;
+ browser->GetTabCountWithTimeout(&old_tab_count, kWaitForActionMaxMsec,
+ &is_timeout);
+ // Apply accelerator and wait for a new tab to open, if either
+ // fails, return false. Apply Accelerator takes care of logging its failure.
+ bool return_value = ApplyAccelerator(IDC_NEWTAB);
+ if (!browser->WaitForTabCountToChange(
+ old_tab_count, &new_tab_count, kWaitForActionMaxMsec)) {
+ AddWarningAttribute("tab_count_failed_to_change");
+ return false;
+ }
+ return return_value;
+}
+
+bool AutomatedUITest::BackButton() {
+ return ApplyAccelerator(IDC_BACK);
+}
+
+bool AutomatedUITest::ForwardButton() {
+ return ApplyAccelerator(IDC_FORWARD);
+}
+
+bool AutomatedUITest::CloseActiveTab() {
+ bool return_value = false;
+ scoped_ptr<BrowserProxy> browser(automation()->GetLastActiveBrowserWindow());
+ if (browser.get() == NULL) {
+ AddErrorAttribute("browser_window_not_found");
+ return false;
+ }
+ int browser_windows_count;
+ int tab_count;
+ bool is_timeout;
+ browser->GetTabCountWithTimeout(&tab_count, kWaitForActionMaxMsec,
+ &is_timeout);
+ automation()->GetBrowserWindowCount(&browser_windows_count);
+ // Avoid quitting the application by not closing the last window.
+ if (tab_count > 1) {
+ int new_tab_count;
+ return_value = browser->ApplyAccelerator(IDC_CLOSETAB);
+ // Wait for the tab to close before we continue.
+ if (!browser->WaitForTabCountToChange(
+ tab_count, &new_tab_count, kWaitForActionMaxMsec)) {
+ AddWarningAttribute("tab_count_failed_to_change");
+ return false;
+ }
+ } else if (tab_count == 1 && browser_windows_count > 1) {
+ int new_window_count;
+ return_value = browser->ApplyAccelerator(IDC_CLOSETAB);
+ // Wait for the window to close before we continue.
+ if (!automation()->WaitForWindowCountToChange(
+ browser_windows_count, &new_window_count, kWaitForActionMaxMsec)) {
+ AddWarningAttribute("window_count_failed_to_change");
+ return false;
+ }
+ } else {
+ AddInfoAttribute("would_have_exited_application");
+ return false;
+ }
+ return return_value;
+}
+
+bool AutomatedUITest::OpenAndActivateNewBrowserWindow() {
+ if (!automation()->OpenNewBrowserWindow(SW_SHOWNORMAL)) {
+ AddWarningAttribute("failed_to_open_new_browser_window");
+ return false;
+ }
+ int num_browser_windows;
+ automation()->GetBrowserWindowCount(&num_browser_windows);
+ // Get the most recently opened browser window and activate the tab
+ // in order to activate this browser window.
+ scoped_ptr<BrowserProxy> browser(
+ automation()->GetBrowserWindow(num_browser_windows - 1));
+ if (browser.get() == NULL) {
+ AddErrorAttribute("browser_window_not_found");
+ return false;
+ }
+ bool is_timeout;
+ if (!browser->ActivateTabWithTimeout(0, kWaitForActionMaxMsec,
+ &is_timeout)) {
+ AddWarningAttribute("failed_to_activate_tab");
+ return false;
+ }
+ return true;
+}
+
+bool AutomatedUITest::ReloadPage() {
+ return ApplyAccelerator(IDC_RELOAD);
+}
+
+bool AutomatedUITest::StarPage() {
+ return ApplyAccelerator(IDC_STAR);
+}
+
+bool AutomatedUITest::FindInPage() {
+ return ApplyAccelerator(IDC_FIND);
+}
+
+bool AutomatedUITest::SelectNextTab() {
+ return ApplyAccelerator(IDC_SELECT_NEXT_TAB);
+}
+
+bool AutomatedUITest::SelectPreviousTab() {
+ return ApplyAccelerator(IDC_SELECT_PREV_TAB);
+}
+
+bool AutomatedUITest::ZoomPlus() {
+ return ApplyAccelerator(IDC_ZOOM_PLUS);
+}
+
+bool AutomatedUITest::ZoomMinus() {
+ return ApplyAccelerator(IDC_ZOOM_MINUS);
+}
+
+bool AutomatedUITest::ShowHistory() {
+ return ApplyAccelerator(IDC_SHOW_HISTORY);
+}
+
+bool AutomatedUITest::ShowDownloads() {
+ return ApplyAccelerator(IDC_SHOW_DOWNLOADS);
+}
+
+bool AutomatedUITest::ImportSettings() {
+ return ApplyAccelerator(IDC_IMPORT_SETTINGS);
+}
+
+bool AutomatedUITest::ViewPasswords() {
+ return ApplyAccelerator(IDC_VIEW_PASSWORDS);
+}
+
+bool AutomatedUITest::ClearBrowserData() {
+ return ApplyAccelerator(IDC_CLEAR_BROWSING_DATA);
+}
+
+bool AutomatedUITest::TaskManager() {
+ return ApplyAccelerator(IDC_TASKMANAGER);
+}
+
+bool AutomatedUITest::GoOffTheRecord() {
+ return ApplyAccelerator(IDC_GOOFFTHERECORD);
+}
+
+bool AutomatedUITest::PressEscapeKey() {
+ return SimulateKeyPressInActiveWindow(VK_ESCAPE, 0);
+}
+
+bool AutomatedUITest::PressTabKey() {
+ return SimulateKeyPressInActiveWindow(VK_TAB, 0);
+}
+
+bool AutomatedUITest::PressEnterKey() {
+ return SimulateKeyPressInActiveWindow(VK_RETURN, 0);
+}
+
+bool AutomatedUITest::PressSpaceBar() {
+ return SimulateKeyPressInActiveWindow(VK_SPACE, 0);
+}
+
+bool AutomatedUITest::PageDown() {
+ return SimulateKeyPressInActiveWindow(VK_PRIOR, 0);
+}
+
+
+bool AutomatedUITest::PageUp() {
+ return SimulateKeyPressInActiveWindow(VK_NEXT, 0);
+}
+
+bool AutomatedUITest::UpArrow() {
+ return SimulateKeyPressInActiveWindow(VK_UP, 0);
+}
+
+bool AutomatedUITest::DownArrow() {
+ return SimulateKeyPressInActiveWindow(VK_DOWN, 0);
+}
+
+bool AutomatedUITest::TestEditKeywords() {
+ DoAction("EditKeywords");
+ return TestDialog(kTestDialogActionsToRun);
+}
+
+bool AutomatedUITest::TestTaskManager() {
+ DoAction("TaskManager");
+ return TestDialog(kTestDialogActionsToRun);
+}
+
+bool AutomatedUITest::TestViewPasswords() {
+ DoAction("ViewPasswords");
+ return TestDialog(kTestDialogActionsToRun);
+}
+
+bool AutomatedUITest::TestClearBrowserData() {
+ DoAction("ClearBrowserData");
+ return TestDialog(kTestDialogActionsToRun);
+}
+
+bool AutomatedUITest::TestImportSettings() {
+ DoAction("ImportSettings");
+ return TestDialog(kTestDialogActionsToRun);
+}
+
+bool AutomatedUITest::TestDialog(int num_actions) {
+ bool return_value = true;
+
+ for (int i = 0; i < num_actions; i++) {
+ int action_index = rand_util::RandInt(0, kNumTestDialogActions - 1);
+ return_value = return_value &&
+ DoAction(test_dialog_possible_actions_[action_index]);
+ if (DidCrash(false))
+ break;
+ }
+ return DoAction("PressEscapeKey") && return_value;
+}
+
+bool AutomatedUITest::ForceCrash() {
+ scoped_ptr<BrowserProxy> browser(automation()->GetLastActiveBrowserWindow());
+ if (browser.get() == NULL) {
+ AddErrorAttribute("browser_window_not_found");
+ return false;
+ }
+ scoped_ptr<TabProxy> tab(browser->GetActiveTab());
+ GURL test_url("about:crash");
+ bool did_timeout;
+ tab->NavigateToURLWithTimeout(test_url, kDebuggingTimeoutMsec, &did_timeout);
+ if (!did_timeout) {
+ AddInfoAttribute("expected_crash");
+ return false;
+ }
+ return true;
+}
+
+bool AutomatedUITest::DragActiveTab(bool drag_right, bool drag_out) {
+ scoped_ptr<BrowserProxy> browser(automation()->GetLastActiveBrowserWindow());
+ scoped_ptr<WindowProxy> window(
+ GetAndActivateWindowForBrowser(browser.get()));
+ if (window.get() == NULL) {
+ AddErrorAttribute("active_window_not_found");
+ return false;
+ }
+ bool is_timeout;
+
+ if (browser.get() == NULL) {
+ AddErrorAttribute("browser_window_not_found");
+ return false;
+ }
+ int tab_count;
+ browser->GetTabCountWithTimeout(&tab_count, kWaitForActionMaxMsec,
+ &is_timeout);
+ // As far as we're concerned, if we can't get a view for a tab, it doesn't
+ // exist, so cap tab_count at the number of tab view ids there are.
+ tab_count = std::min(tab_count, VIEW_ID_TAB_LAST - VIEW_ID_TAB_0);
+
+ int tab_index;
+ if (!browser->GetActiveTabIndexWithTimeout(&tab_index,
+ kWaitForActionMaxMsec,
+ &is_timeout)) {
+ AddWarningAttribute("no_active_tab");
+ return false;
+ }
+
+ gfx::Rect dragged_tab_bounds;
+ if (!window->GetViewBoundsWithTimeout(VIEW_ID_TAB_0 + tab_index,
+ &dragged_tab_bounds, false,
+ kWaitForActionMaxMsec,
+ &is_timeout)) {
+ AddWarningAttribute("no_tab_view_found");
+ return false;
+ }
+
+ // Click on the center of the tab, and drag it to the left or the right.
+ POINT dragged_tab_point(dragged_tab_bounds.CenterPoint().ToPOINT());
+ POINT destination_point(dragged_tab_point);
+
+ int window_count;
+ if (drag_out) {
+ destination_point.y += 3*dragged_tab_bounds.height();
+ automation()->GetBrowserWindowCount(&window_count);
+ } else if (drag_right) {
+ if (tab_index >= (tab_count-1)) {
+ AddInfoAttribute("index_cant_be_moved");
+ return false;
+ }
+ destination_point.x += 2*dragged_tab_bounds.width()/3;
+ } else {
+ if (tab_index <= 0) {
+ AddInfoAttribute("index_cant_be_moved");
+ return false;
+ }
+ destination_point.x -= 2*dragged_tab_bounds.width()/3;
+ }
+
+ if (!browser->SimulateDragWithTimeout(dragged_tab_point,
+ destination_point,
+ ChromeViews::Event::EF_LEFT_BUTTON_DOWN,
+ kWaitForActionMaxMsec,
+ &is_timeout)) {
+ AddWarningAttribute("failed_to_simulate_drag");
+ return false;
+ }
+
+ // If we try to drag the tab out and the window we drag from contains more
+ // than just the dragged tab, we would expect the window count to increase
+ // because the dragged tab should open in a new window. If not, we probably
+ // just dragged into another tabstrip.
+ if (drag_out && tab_count > 1) {
+ int new_window_count;
+ automation()->GetBrowserWindowCount(&new_window_count);
+ if (new_window_count == window_count) {
+ AddInfoAttribute("no_new_browser_window");
+ return false;
+ }
+ }
+ return true;
+}
+
+WindowProxy* AutomatedUITest::GetAndActivateWindowForBrowser(
+ BrowserProxy* browser) {
+ WindowProxy* window = automation()->GetWindowForBrowser(browser);
+
+ bool did_timeout;
+ if (!browser->BringToFrontWithTimeout(kWaitForActionMaxMsec, &did_timeout)) {
+ AddWarningAttribute("failed_to_bring_window_to_front");
+ return NULL;
+ }
+ return window;
+}
+
+bool AutomatedUITest::ApplyAccelerator(int id) {
+ scoped_ptr<BrowserProxy> browser(automation()->GetLastActiveBrowserWindow());
+ if (browser.get() == NULL) {
+ AddErrorAttribute("browser_window_not_found");
+ return false;
+ }
+ if (!browser->ApplyAccelerator(id)) {
+ AddWarningAttribute("failure_applying_accelerator");
+ return false;
+ }
+ return true;
+}
+
+bool AutomatedUITest::SimulateKeyPressInActiveWindow(wchar_t key, int flags) {
+ scoped_ptr<BrowserProxy> browser(automation()->GetLastActiveBrowserWindow());
+ scoped_ptr<WindowProxy> window(
+ GetAndActivateWindowForBrowser(browser.get()));
+ if (window.get() == NULL) {
+ AddErrorAttribute("active_window_not_found");
+ return false;
+ }
+ if (!window->SimulateOSKeyPress(key, flags)) {
+ AddWarningAttribute("failure_simulating_key_press");
+ return false;
+ }
+ return true;
+}
+
+bool AutomatedUITest::InitXMLReader() {
+ std::wstring input_path;
+ CommandLine parsed_command_line;
+ if (parsed_command_line.HasSwitch(kInputFilePathSwitch))
+ input_path = parsed_command_line.GetSwitchValue(kInputFilePathSwitch);
+ else
+ input_path = kDefaultInputFilePath;
+
+ if (!file_util::ReadFileToString(input_path, &xml_init_file_))
+ return false;
+ return init_reader_.Load(xml_init_file_);
+}
+
+bool AutomatedUITest::WriteReportToFile() {
+ std::ofstream error_file;
+ std::wstring path;
+ CommandLine parsed_command_line;
+ if (parsed_command_line.HasSwitch(kOutputFilePathSwitch))
+ path = parsed_command_line.GetSwitchValue(kOutputFilePathSwitch);
+ else
+ path = kDefaultOutputFilePath;
+
+ if (!path.empty())
+ error_file.open(path.c_str(), std::ios::out);
+
+ // Closes all open elements and free the writer. This is required
+ // in order to retrieve the contents of the buffer.
+ xml_writer_.StopWriting();
+ error_file << xml_writer_.GetWrittenString();
+ error_file.close();
+ return true;
+}
+
+void AutomatedUITest::AppendToOutputFile(const std::string &append_string) {
+ std::ofstream error_file;
+ std::wstring path;
+ CommandLine parsed_command_line;
+ if (parsed_command_line.HasSwitch(kOutputFilePathSwitch))
+ path = parsed_command_line.GetSwitchValue(kOutputFilePathSwitch);
+ else
+ path = kDefaultOutputFilePath;
+
+ if (!path.empty())
+ error_file.open(path.c_str(), std::ios::out | std::ios_base::app);
+
+ error_file << append_string << " ";
+ error_file.close();
+}
+
+void AutomatedUITest::LogCrashResult(const std::string &crash_dump,
+ bool command_completed) {
+ xml_writer_.StartElement("result");
+ xml_writer_.StartElement("crash");
+ xml_writer_.AddAttribute("crash_dump", crash_dump);
+ if (command_completed)
+ xml_writer_.AddAttribute("command_completed", "yes");
+ else
+ xml_writer_.AddAttribute("command_completed", "no");
+ xml_writer_.EndElement();
+ xml_writer_.EndElement();
+}
+
+void AutomatedUITest::LogSuccessResult() {
+ xml_writer_.StartElement("result");
+ xml_writer_.StartElement("success");
+ xml_writer_.EndElement();
+ xml_writer_.EndElement();
+}
+
+void AutomatedUITest::AddInfoAttribute(const std::string &info) {
+ xml_writer_.AddAttribute("info", info);
+}
+
+void AutomatedUITest::AddWarningAttribute(const std::string &warning) {
+ xml_writer_.AddAttribute("warning", warning);
+}
+
+void AutomatedUITest::AddErrorAttribute(const std::string &error) {
+ xml_writer_.AddAttribute("error", error);
+}
+
+std::wstring AutomatedUITest::GetMostRecentCrashDump() {
+ std::wstring crash_dump_path;
+ int file_count = 0;
+ FILETIME most_recent_file_time;
+ std::wstring most_recent_file_name;
+ WIN32_FIND_DATA find_file_data;
+
+ PathService::Get(chrome::DIR_CRASH_DUMPS, &crash_dump_path);
+ // All files in the given directory.
+ std::wstring filename_spec = crash_dump_path + L"\\*";
+ HANDLE find_handle = FindFirstFile(filename_spec.c_str(), &find_file_data);
+ if (find_handle != INVALID_HANDLE_VALUE) {
+ most_recent_file_time = find_file_data.ftCreationTime;
+ most_recent_file_name = find_file_data.cFileName;
+ do {
+ // Don't count current or parent directories.
+ if ((wcscmp(find_file_data.cFileName, L"..") == 0) ||
+ (wcscmp(find_file_data.cFileName, L".") == 0))
+ continue;
+
+ long result = CompareFileTime(&find_file_data.ftCreationTime,
+ &most_recent_file_time);
+
+ // File was created on or after the current most recent file.
+ if ((result == 1) || (result == 0)) {
+ most_recent_file_time = find_file_data.ftCreationTime;
+ most_recent_file_name = find_file_data.cFileName;
+ }
+ } while (FindNextFile(find_handle, &find_file_data));
+ FindClose(find_handle);
+ }
+
+ if (most_recent_file_name.empty()) {
+ return L"";
+ } else {
+ file_util::AppendToPath(&crash_dump_path, most_recent_file_name);
+ return crash_dump_path;
+ }
+}
+
+bool AutomatedUITest::DidCrash(bool update_total_crashes) {
+ std::wstring crash_dump_path;
+ PathService::Get(chrome::DIR_CRASH_DUMPS, &crash_dump_path);
+ // Each crash creates two dump files, so we divide by two here.
+ int actual_crashes = file_util::CountFilesCreatedAfter(
+ crash_dump_path, test_start_time_) / 2;
+
+ // If there are more crash dumps than the total dumps which we have recorded
+ // then this is a new crash.
+ if (actual_crashes > total_crashes_) {
+ if (update_total_crashes)
+ total_crashes_ = actual_crashes;
+ return true;
+ } else {
+ return false;
+ }
+}
+
+TEST_F(AutomatedUITest, TheOneAndOnlyTest) {
+ CommandLine parsed_command_line;
+ if (parsed_command_line.HasSwitch(kReproSwitch))
+ RunReproduction();
+ else
+ RunAutomatedUITest();
+}
diff --git a/chrome/test/automated_ui_tests/automated_ui_tests.h b/chrome/test/automated_ui_tests/automated_ui_tests.h
new file mode 100644
index 0000000..96475ee
--- /dev/null
+++ b/chrome/test/automated_ui_tests/automated_ui_tests.h
@@ -0,0 +1,443 @@
+// 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.
+
+#ifndef CHROME_TEST_AUTOMATED_UI_TESTS_AUTOMATED_UI_TESTS_H__
+#define CHROME_TEST_AUTOMATED_UI_TESTS_AUTOMATED_UI_TESTS_H__
+
+// This takes an input file of commands, which consist of a series of
+// actions, and runs every command, reporting the status of each one
+// to an output file once all the commands have been run.
+//
+// The input file should be an XML file that has a root of any name followed
+// by a series of elements named "command" with child elements representing
+// the various actions, in order, to be performed during each command. A
+// command element can optionally include an "number" attribute to identify it.
+//
+// Example:
+// <CommandList>
+// <command number="1"><NewTab/><Navigate/><OpenWindow/><Navigate/><Back/>
+// </command>
+// <command number="2"><NewTab/><Navigate/><Navigate/><Back/><Forward/>
+// </command>
+// <command number="3"><CloseTab/><OpenWindow/><NewTab/><Navigate/><CloseTab/>
+// </command>
+// </CommandList>
+//
+// When the test is finished it will output results to the output file,
+// overwriting any previous version of this file. The output file is an
+// XML file which reports on each command, indicating whether it successfully
+// ran and if there were any errors.
+//
+// Example: (actual output will probably contain more actions per command):
+// <Report>
+// <Executed command_number="1"><NewTab/><Navigate/><result><success/>
+// </result> </Executed>
+// <Executed command_number="2"><Back/><Forward/><result><success/></result>
+// </Executed>
+// <Executed command_number="3"><CloseTab/><result>
+// <crash crash_dump="C:\a_crash.txt" command_completed="no"/></result>
+// </Executed>
+// </Report>
+//
+// A "crash" result will have two attributes, crash_dump, which points
+// to the full path of crash dump associated with this crash, and
+// command_completed which indicates whether or not the last
+// action recorded was the final action of the command.
+//
+// Furthermore, each individual action may contain additional attributes
+// to log non-fatal failures. If the attribute 'failed_to_complete="yes"'
+// is present, then the action did not complete. If that attribute is present,
+// an info, warning, or error attribute will also be present, and will contain
+// a string describing the error. The presence of info means the failure was
+// expected, probably due to a state making the action impossible to perform
+// like trying to close the last remaining window. Warnings usually mean the
+// action couldn't complete for an unknown and unexpected reason, but that the
+// test state is probably fine. Errors are like warnings, but they mean the test
+// state is probably incorrect, and more failures are likely to be caused by
+// the same problem.
+//
+// Example of some failed actions:
+// <CloseTab failed_to_complete="yes" info="would_have_exited_application"/>
+// <Reload failed_to_complete="yes" warning="failed_to_apply_accelerator"/>
+// <Star failed_to_complete="yes" error="browser_window_not_found"/>
+//
+//
+// Switches
+// --input : Specifies the input file, must be an absolute directory.
+// Default is "C:\automated_ui_tests.txt"
+//
+// --output : Specifies the output file, must be an absolute directory.
+// Default is "C:\automated_ui_tests_error_report.txt"
+//
+//
+// Test reproduction options:
+//
+// If you're trying to reproduce the results from crash reports use the
+// following switches
+//
+// --key : Specifies, via a comma delimited list, what actions to run. Examples:
+// --key=SetUp,ZoomPlus,Forward,History,Navigate,Back,TearDown
+// --key=SetUp,ZoomPlus
+// Note, the second key doesn't include a TearDown, that will
+// automatically be added if the result doesn't crash.
+//
+// --num-reproductions : Specifies the number of reproductions to run, the
+// default is 1. Suggested use: run without this flag
+// to see if we reproduce a crash, then run with the flag
+// if there isn't a crash, to see if it might be a rare
+// race condition that causes the crash.
+//
+//
+// Debugging options:
+//
+// --debug : Will append each action that is performed to the output file, as
+// soon as the action is performed. If the program finishes, this file
+// will be overwritten with the normal results. This flag is used to
+// help debug the tests if they are crashing before they get a chance
+// to write their results to file.
+
+#include "chrome/test/ui/ui_test.h"
+
+// Size of the array of possible actions to use when testing a dialog.
+const int kNumTestDialogActions = 4;
+
+class AutomatedUITest : public UITest {
+ protected:
+ AutomatedUITest();
+ ~AutomatedUITest();
+
+ // Runs a reproduction of one set of actions, reporting whether they crash
+ // or not.
+ void RunReproduction();
+
+ // Runs automated UI tests which are read from the input file.
+ // Reports crashes to the output file.
+ void RunAutomatedUITest();
+
+ // Attempts to perform an action based on the input string. See below for
+ // possible actions. Returns true if the action completes, false otherwise.
+ bool DoAction(const std::string &action);
+
+ // Actions ------------------------------------------------------------------
+
+ // Navigates the activate tab to about:blank.
+ // XML element: <Navigate/>
+ // Optional Attributes: url="|address|" will navigate to |address|
+ bool Navigate();
+
+ // Opens a new tab in the active window using an accelerator.
+ // Returns true if call to activate the accelerator is successful.
+ // XML element: <NewTab/>
+ bool NewTab();
+
+ // Activates back button in active window.
+ // Returns true if call to activate the accelerator is successful.
+ // XML element: <Back/>
+ bool BackButton();
+
+ // Activates forward button in active window.
+ // Returns true if call to activate the accelerator is successful.
+ // XML element: <Forward/>
+ bool ForwardButton();
+
+ // Uses accelerator to close the active tab if it isn't the only tab.
+ // Returns false if active tab is the only tab, true otherwise.
+ // XML element: <CloseTab/>
+ bool CloseActiveTab();
+
+ // Opens a new browser window by calling automation()->OpenNewBrowserWindow
+ // Then activates the tab opened in the new window.
+ // Returns true if window is successfully created.
+ // XML element: <OpenWindow/>
+ bool OpenAndActivateNewBrowserWindow();
+
+ // Reload the active tab. Returns false on failure.
+ // XML element: <Reload/>
+ bool ReloadPage();
+
+ // Stars the current page. This opens a dialog that may or may not be
+ // dismissed.
+ // XML element: <Star/>
+ bool StarPage();
+
+ // Activates "find in page" on the current page.
+ // XML element: <FindInPage/>
+ bool FindInPage();
+
+ // Activates the next tab on the active browser window.
+ // XML element: <SelectNextTab/>
+ bool SelectNextTab();
+
+ // Activates the previous tab on the active browser window.
+ // XML element: <SelectPrevTab/>
+ bool SelectPreviousTab();
+
+ // Increases the text size on the current active tab.
+ // XML element: <ZoomPlus/>
+ bool ZoomPlus();
+
+ // Decreases the text size on the current active tab.
+ // XML element: <ZoomMinus/>
+ bool ZoomMinus();
+
+ // Opens the History page in the current active browser window.
+ // XML element: <History/>
+ bool ShowHistory();
+
+ // Opens the Downloads page in the current active browser window.
+ // XML element: <Downloads/>
+ bool ShowDownloads();
+
+ // Opens the Import Settings dialog, this dialog is modal so a majority of
+ // the test can't be completed until it is dismissed.
+ // XML element: <ImportSettings/>
+ bool ImportSettings();
+
+ // Opens the View Passwords dialog, this dialog is modal so a majority of
+ // the test can't be completed until it is dismissed.
+ // XML element: <ViewPasswords/>
+ bool ViewPasswords();
+
+ // Opens the Clear Browser Data dialog, this dialog is modal so a majority of
+ // the test can't be completed until it is dismissed.
+ // XML element: <ClearBrowserData/>
+ bool ClearBrowserData();
+
+ // Opens the Task Manager dialog. While it isn't modal, it takes focus from
+ // the current browser window, so most of the test can't continue until is
+ // dismissed.
+ // XML element: <TaskManager/>
+ bool TaskManager();
+
+ // Opens and focuses an OffTheRecord browser window.
+ // XML element: <GoOffTheRecord/>
+ bool GoOffTheRecord();
+
+ // Simulates an escape key press on the active window.
+ // XML element: <PressEscapeKey/>
+ bool PressEscapeKey();
+
+ // Simulates a tab key press on the active window.
+ // XML element: <PressTabKey/>
+ bool PressTabKey();
+
+ // Simulates an enter key press on the active window.
+ // XML element: <PressEnterKey/>
+ bool PressEnterKey();
+
+ // Simulates a space bar press on the active window.
+ // XML element: <PressSpaceBar/>
+ bool PressSpaceBar();
+
+ // Simulates a page down key press on the active window.
+ // XML element: <PageDown/>
+ bool PageDown();
+
+ // Simulates a page up key press on the active window.
+ // XML element: <PageUp/>
+ bool PageUp();
+
+ // Simulates a page up key press on the active window.
+ // XML element: <UpArrow/>
+ bool UpArrow();
+
+ // Simulates a page up key press on the active window.
+ // XML element: <DownArrow/>
+ bool DownArrow();
+
+ // Test Dialog Actions ******************************************************
+ // These are a special set of actions that perform multiple actions on a
+ // specified dialog. They run kTestDialogActionsToRun actions randomly
+ // chosen from test_dialog_possible_actions_ after opening the dialog. They
+ // then always end with a PressEscapeKey action, to attempt to close the
+ // dialog.
+ //
+ // The randomly performed actions are logged as child elements of the
+ // TestDialog action. For example (for kTestDialogActionsToRun = 4):
+ // <TestEditKeywords> <PressTabKey/><PressEnterKey/><DownArrow/>
+ // <DownArrow/><PressEscapeKey/> </TestEditKeywords>
+
+ // Opens Edit Keywords dialog and runs random actions on it.
+ // XML element: <TestEditKeywords/>
+ bool TestEditKeywords();
+
+ // Opens Task Manager and runs random actions on it.
+ // This has the possibility of killing both the browser and renderer
+ // processes, which will cause non-fatal errors for the remaining actions
+ // in this command.
+ // XML element: <TestTaskManager/>
+ bool TestTaskManager();
+
+ // Opens View Passwords dialog and runs random actions on it.
+ // XML element: <TestViewPasswords/>
+ bool TestViewPasswords();
+
+ // Opens Clear Browser Data dialog and runs random actions on it.
+ // XML element: <TestClearBrowserData/>
+ bool TestClearBrowserData();
+
+ // Opens Import Settings dialog and runs random actions on it.
+ // XML element: <TestImportSettings/>
+ bool TestImportSettings();
+
+ // End Test Dialog Actions **************************************************
+
+ // Runs a limited set of actions designed to test dialogs. Will run
+ // |num_actions| from the set defined in test_dialog_possible_actions_.
+ bool TestDialog(int num_actions);
+
+ // Navigates to about:crash.
+ // XML element: <Crash/>
+ bool ForceCrash();
+
+ // Drags the active tab. If |drag_out| is true, |drag_right| is ignored and
+ // the tab is dragged vertically to remove it from the tabstrip. Otherwise,
+ // If |drag_right| is true, if there is a tab to the right of the active tab,
+ // the active tab is dragged to that tabs position. If |drag_right| is false,
+ // if there is a tab to the left of the active tab, the active tab is dragged
+ // to that tabs position. Returns false if the tab isn't dragged, or if an
+ // attempt to drag out doesn't create a new window (likely because it was
+ // dragged in to another window).
+ // XML element (multiple elements use this):
+ // <DragTabRight/> - Calls DragActiveTab(true, false) (attempt to drag right)
+ // <DragTabLeft/> - Calls DragActiveTab(false, false) (attempt to drag left)
+ // <DragTabOut/> - Calls DragActiveTab(false, true) (attempt to drag tab out)
+ bool DragActiveTab(bool drag_right, bool drag_out);
+
+ // Utility functions --------------------------------------------------------
+
+ // Returns the WindowProxy associated with the given BrowserProxy
+ // (transferring ownership of the pointer to the caller) and brings that
+ // window to the top.
+ WindowProxy* GetAndActivateWindowForBrowser(BrowserProxy* browser);
+
+ // Applies the accelerator with the given ID to the current active window.
+ // Returns true if the call is successful.
+ // Returns false if the active window is not a browser window or if the
+ // message to apply the accelerator fails.
+ bool ApplyAccelerator(int id);
+
+ // Calls SimulateOSKeyPress on the active window. Simulates a key press at
+ // the OS level. |key| is the key pressed and |flags| specifies which
+ // modifiers keys are also pressed (as defined inchrome/views/event.h).
+ bool SimulateKeyPressInActiveWindow(wchar_t key, int flags);
+
+ // Opens init file, reads it into the reader, and closes the file.
+ // Returns false if there are any errors.
+ bool InitXMLReader();
+
+ // Closes the xml_writer and outputs the contents of its buffer to
+ // the output file.
+ bool WriteReportToFile();
+
+ // Appends the provided string to the output file.
+ void AppendToOutputFile(const std::string &append_string);
+
+ // Logs a crash to the xml_writer in the form of:
+ // <result><crash crash_dump="|crash_dump|" command_completed="yes/no"/>
+ // </result>
+ // crash_dump - Location of crash dump if applicable.
+ // command_completed - True if all actions in the command were completed
+ // before the crash occured.
+ void LogCrashResult(const std::string &crash_dump, bool command_completed);
+
+ // Logs a successful command to the xml_writer in the form of:
+ // <result><success/><result/>
+ void LogSuccessResult();
+
+ // Adds the attribute "reason=|reason|" to the current element.
+ // Used to log the reason for a given failure while performing an action.
+ void LogActionFailureReason(const std::string &reason);
+
+ // Adds the attribute 'info="|info|"' to the current element. Used when an
+ // action could not complete for a non-serious issue. Usually because the
+ // state of the test wouldn't allow for a particular action.
+ void AddInfoAttribute(const std::string &info);
+
+ // Adds the attribute "warning=|warning|" to the current element. Used when
+ // an action could not complete because of a potentially troublesome issue.
+ void AddWarningAttribute(const std::string &warning);
+
+ // Adds the attribute "error=|error|" to the current element. Used when an
+ // action could not complete due to an unexpected problem which might
+ // invalidate the results of the entire command (not just the action).
+ // This is usually used when the testing environment isn't acting as we'd
+ // expect. For example, no chrome windows are focused, or key presses aren't
+ // being registered.
+ void AddErrorAttribute(const std::string &error);
+
+ // Returns the full path of the crash dump. This is likely to be the
+ // .txt file, not the actual crash dump. Although they do share
+ // a common name.
+ std::wstring GetMostRecentCrashDump();
+
+ // Returns true if the test has produced any new crash logs.
+ // A "new" crash log is one that was produced since DidCrash was last called
+ // with |update_total_crashes| set to true.
+ bool DidCrash(bool update_total_crashes);
+
+ // Overridden so that UI Test doesn't set up when the tests start.
+ // We use DoAction("SetUp") to set up, because it logs it and makes
+ // it easier to check for crashes when we start the browser.
+ virtual void SetUp() {}
+
+ // Overridden so that UI Test doesn't close the browser (which is already
+ // closed) at the end of the test.
+ // We use DoAction("TearDown") to tear down, because it logs it and makes
+ // it easier to check for crashes when we close the browser.
+ virtual void TearDown() {}
+
+ private:
+ // Parses the init file.
+ XmlReader init_reader_;
+
+ // Builds the output file.
+ XmlWriter xml_writer_;
+
+ // Time the test was started. Used to find crash dumps.
+ FILETIME test_start_time_;
+
+ // Number of times the browser has crashed during this run.
+ // Used to check for new crashes.
+ int total_crashes_;
+
+ // Used to init the init_reader_. It must exist as long as the reader does.
+ std::string xml_init_file_;
+
+ // If true, appends the commands to the output file as they are executed.
+ // Used for debugging when automated_ui_tests.cc crashes before it outputs
+ // results.
+ bool debug_logging_enabled_;
+
+ static std::string test_dialog_possible_actions_[kNumTestDialogActions];
+
+ DISALLOW_EVIL_CONSTRUCTORS(AutomatedUITest);
+};
+
+#endif // #define CHROME_TEST_AUTOMATED_UI_TESTS_AUTOMATED_UI_TESTS_H__
diff --git a/chrome/test/automated_ui_tests/automated_ui_tests.vcproj b/chrome/test/automated_ui_tests/automated_ui_tests.vcproj
new file mode 100644
index 0000000..71914d1
--- /dev/null
+++ b/chrome/test/automated_ui_tests/automated_ui_tests.vcproj
@@ -0,0 +1,212 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="automated_ui_tests"
+ ProjectGUID="{D2250C20-3A94-4FB9-AF73-11BC5B73884B}"
+ RootNamespace="page_cycler_tests"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ ConfigurationType="1"
+ InheritedPropertySheets="$(SolutionDir)..\build\common.vsprops;$(SolutionDir)..\build\debug.vsprops;..\..\tools\build\win\precompiled_wtl.vsprops;..\..\tools\build\win\unit_test.vsprops;..\..\tools\build\win\ui_test.vsprops;$(SolutionDir)..\skia\using_skia.vsprops;$(SolutionDir)..\third_party\libxml\build\using_libxml.vsprops;$(SolutionDir)..\third_party\icu38\build\using_icu.vsprops;..\..\tools\build\win\test_memory_usage.vsprops;$(SolutionDir)..\testing\using_gtest.vsprops"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ />
+ <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"
+ ConfigurationType="1"
+ InheritedPropertySheets="$(SolutionDir)..\build\common.vsprops;$(SolutionDir)..\build\release.vsprops;..\..\tools\build\win\unit_test.vsprops;..\..\tools\build\win\ui_test.vsprops;..\..\tools\build\win\test_memory_usage.vsprops;$(SolutionDir)..\skia\using_skia.vsprops;$(SolutionDir)..\third_party\libxml\build\using_libxml.vsprops;$(SolutionDir)..\third_party\icu38\build\using_icu.vsprops;$(SolutionDir)..\testing\using_gtest.vsprops"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ />
+ <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="Common"
+ >
+ <File
+ RelativePath="..\..\tools\build\win\precompiled_wtl.cc"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="1"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\tools\build\win\precompiled_wtl.h"
+ >
+ </File>
+ <File
+ RelativePath="..\ui\run_all_unittests.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\test_file_util.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\testing_browser_process.h"
+ >
+ </File>
+ <File
+ RelativePath="..\ui\ui_test.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\ui\ui_test.h"
+ >
+ </File>
+ <File
+ RelativePath="..\ui\ui_test_suite.cc"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="MemoryUsage"
+ >
+ <File
+ RelativePath="..\perf\mem_usage.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\perf\mem_usage.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="AutomatedUITest"
+ >
+ <File
+ RelativePath=".\automated_ui_tests.cc"
+ >
+ </File>
+ <File
+ RelativePath=".\automated_ui_tests.h"
+ >
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/chrome/test/automation/SConscript b/chrome/test/automation/SConscript
new file mode 100644
index 0000000..79286f2
--- /dev/null
+++ b/chrome/test/automation/SConscript
@@ -0,0 +1,58 @@
+# 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.
+
+Import('env')
+
+env = env.Clone()
+
+env.Prepend(
+ CPPPATH = [
+ #'../../..',
+ #'$GTEST_DIR/include',
+ '$SKIA_DIR/include',
+ '$SKIA_DIR/include/corecg',
+ '$SKIA_DIR/platform',
+ '#/..',
+ ],
+)
+
+input_files = [
+ 'autocomplete_edit_proxy.cc',
+ 'automation_handle_tracker.cc',
+ 'automation_proxy.cc',
+ 'browser_proxy.cc',
+ 'constrained_window_proxy.cc',
+ 'tab_proxy.cc',
+ 'window_proxy.cc',
+]
+
+lib = env.StaticLibrary('automation', input_files)
+
+i = env.Install('$TARGET_ROOT', lib)
+env.Alias('chrome', i)
diff --git a/chrome/test/automation/autocomplete_edit_proxy.cc b/chrome/test/automation/autocomplete_edit_proxy.cc
new file mode 100644
index 0000000..33303ad
--- /dev/null
+++ b/chrome/test/automation/autocomplete_edit_proxy.cc
@@ -0,0 +1,136 @@
+// 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.
+
+#include "chrome/test/automation/autocomplete_edit_proxy.h"
+
+#include <vector>
+
+#include "chrome/test/automation/automation_constants.h"
+#include "chrome/test/automation/automation_messages.h"
+#include "chrome/test/automation/automation_proxy.h"
+
+bool AutocompleteEditProxy::GetText(std::wstring* text) const {
+ if (!is_valid())
+ return false;
+ if (!text) {
+ NOTREACHED();
+ return false;
+ }
+
+ IPC::Message* response = NULL;
+ if (!sender_->SendAndWaitForResponse(
+ new AutomationMsg_AutocompleteEditGetTextRequest(0, handle_), &response,
+ AutomationMsg_AutocompleteEditGetTextResponse::ID))
+ return false;
+ scoped_ptr<IPC::Message> response_deleter(response);
+
+ Tuple2<bool, std::wstring> returned_result;
+ if (!AutomationMsg_AutocompleteEditGetTextResponse::Read(response,
+ &returned_result) || !returned_result.a)
+ return false;
+
+ text->swap(returned_result.b);
+ return true;
+}
+
+bool AutocompleteEditProxy::SetText(const std::wstring& text) {
+ if (!is_valid())
+ return false;
+
+ IPC::Message* response = NULL;
+ if (!sender_->SendAndWaitForResponse(
+ new AutomationMsg_AutocompleteEditSetTextRequest(0, handle_, text),
+ &response, AutomationMsg_AutocompleteEditSetTextResponse::ID))
+ return false;
+
+ delete response;
+ return true;
+}
+
+bool AutocompleteEditProxy::IsQueryInProgress(bool* query_in_progress) const {
+ if (!is_valid())
+ return false;
+ if (!query_in_progress) {
+ NOTREACHED();
+ return false;
+ }
+
+ IPC::Message* response = NULL;
+ if (!sender_->SendAndWaitForResponse(
+ new AutomationMsg_AutocompleteEditIsQueryInProgressRequest(0, handle_),
+ &response, AutomationMsg_AutocompleteEditIsQueryInProgressResponse::ID))
+ return false;
+ scoped_ptr<IPC::Message> response_deleter(response);
+
+ Tuple2<bool, bool> returned_result;
+ if (!AutomationMsg_AutocompleteEditIsQueryInProgressResponse::Read(
+ response, &returned_result) || !returned_result.a)
+ return false;
+
+ *query_in_progress = returned_result.b;
+ return true;
+}
+
+
+bool AutocompleteEditProxy::WaitForQuery(int wait_timeout_ms) const {
+ const TimeTicks start = TimeTicks::Now();
+ const TimeDelta timeout = TimeDelta::FromMilliseconds(wait_timeout_ms);
+ bool query_in_progress;
+ while (TimeTicks::Now() - start < timeout) {
+ if (IsQueryInProgress(&query_in_progress) && !query_in_progress)
+ return true;
+ Sleep(automation::kSleepTime);
+ }
+ // If we get here the query is still in progress.
+ return false;
+}
+
+bool AutocompleteEditProxy::GetAutocompleteMatches(Matches* matches) const {
+ if (!is_valid())
+ return false;
+ if (!matches) {
+ NOTREACHED();
+ return false;
+ }
+
+ IPC::Message* response = NULL;
+ if (!sender_->SendAndWaitForResponse(
+ new AutomationMsg_AutocompleteEditGetMatchesRequest(0, handle_),
+ &response, AutomationMsg_AutocompleteEditGetMatchesResponse::ID))
+ return false;
+ scoped_ptr<IPC::Message> response_deleter(response);
+
+ Tuple2<bool, Matches> returned_result;
+ if (!AutomationMsg_AutocompleteEditGetMatchesResponse::Read(
+ response, &returned_result) || !returned_result.a)
+ return false;
+
+ *matches = returned_result.b;
+ return true;
+}
diff --git a/chrome/test/automation/autocomplete_edit_proxy.h b/chrome/test/automation/autocomplete_edit_proxy.h
new file mode 100644
index 0000000..608d1f1
--- /dev/null
+++ b/chrome/test/automation/autocomplete_edit_proxy.h
@@ -0,0 +1,169 @@
+// 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.
+
+#ifndef CHROME_TEST_AUTOMATION_AUTOCOMPLETE_EDIT_PROXY_H__
+#define CHROME_TEST_AUTOMATION_AUTOCOMPLETE_EDIT_PROXY_H__
+
+#include <string>
+#include <vector>
+
+#include "chrome/browser/autocomplete/autocomplete.h"
+#include "chrome/common/ipc_message.h"
+#include "chrome/common/ipc_message_utils.h"
+#include "chrome/test/automation/automation_handle_tracker.h"
+
+// The purpose of this class is to act as a searializable version of
+// AutocompleteMatch. The reason for this class is because we don't want to
+// searialize all elements of AutocompleteMatch and we want some data from the
+// autocomplete provider without the hassle of serializing it.
+struct AutocompleteMatchData {
+ public:
+ AutocompleteMatchData() {}
+ explicit AutocompleteMatchData(const AutocompleteMatch& match)
+ : contents(match.contents),
+ deletable(match.deletable),
+ description(match.description),
+ destination_url(match.destination_url),
+ fill_into_edit(match.fill_into_edit),
+ inline_autocomplete_offset(match.inline_autocomplete_offset),
+ is_history_what_you_typed_match(match.is_history_what_you_typed_match),
+ provider_name(match.provider->name()),
+ relevance(match.relevance),
+ starred(match.starred) {
+ switch (match.type) {
+ case AutocompleteMatch::URL:
+ str_type = L"URL";
+ break;
+ case AutocompleteMatch::KEYWORD:
+ str_type = L"KEYWORD";
+ break;
+ case AutocompleteMatch::SEARCH:
+ str_type = L"SEARCH";
+ break;
+ case AutocompleteMatch::HISTORY_SEARCH:
+ str_type = L"HISTORY";
+ break;
+ default:
+ NOTREACHED();
+ }
+ }
+ std::wstring contents;
+ bool deletable;
+ std::wstring description;
+ std::wstring destination_url;
+ std::wstring fill_into_edit;
+ size_t inline_autocomplete_offset;
+ bool is_history_what_you_typed_match;
+ std::string provider_name;
+ int relevance;
+ bool starred;
+ std::wstring str_type;
+};
+typedef std::vector<AutocompleteMatchData> Matches;
+
+namespace IPC {
+
+template <>
+struct ParamTraits<AutocompleteMatchData> {
+ typedef AutocompleteMatchData param_type;
+ static void Write(Message* m, const param_type& p) {
+ m->WriteWString(p.contents);
+ m->WriteBool(p.deletable);
+ m->WriteWString(p.description);
+ m->WriteWString(p.destination_url);
+ m->WriteWString(p.fill_into_edit);
+ m->WriteSize(p.inline_autocomplete_offset);
+ m->WriteBool(p.is_history_what_you_typed_match);
+ m->WriteString(p.provider_name);
+ m->WriteInt(p.relevance);
+ m->WriteBool(p.starred);
+ m->WriteWString(p.str_type);
+ }
+
+ static bool Read(const Message* m, void** iter, param_type* r) {
+ return m->ReadWString(iter, &r->contents) &&
+ m->ReadBool(iter, &r->deletable) &&
+ m->ReadWString(iter, &r->description) &&
+ m->ReadWString(iter, &r->destination_url) &&
+ m->ReadWString(iter, &r->fill_into_edit) &&
+ m->ReadSize(iter, &r->inline_autocomplete_offset) &&
+ m->ReadBool(iter, &r->is_history_what_you_typed_match) &&
+ m->ReadString(iter, &r->provider_name) &&
+ m->ReadInt(iter, &r->relevance) &&
+ m->ReadBool(iter, &r->starred) &&
+ m->ReadWString(iter, &r->str_type);
+ }
+
+ static void Log(const param_type& p, std::wstring* l) {
+ l->append(StringPrintf(L"[%S %s %S %S %S %d %s %s %d %s %S]",
+ p.contents, p.deletable ? "true" : "false", p.description,
+ p.destination_url, p.fill_into_edit, p.inline_autocomplete_offset,
+ p.is_history_what_you_typed_match ? "true" : "false", p.provider_name,
+ p.relevance, p.starred ? "true" : "false", p.str_type));
+ }
+};
+} // namespace IPC
+
+class AutocompleteEditProxy : public AutomationResourceProxy {
+ public:
+ AutocompleteEditProxy(AutomationMessageSender* sender,
+ AutomationHandleTracker* tracker,
+ int handle)
+ : AutomationResourceProxy(tracker, sender, handle) {}
+ virtual ~AutocompleteEditProxy() {}
+
+ // All these functions return true if the autocomplete edit is valid and
+ // there are no IPC errors.
+
+ // Gets the text visible in the omnibox.
+ bool GetText(std::wstring* text) const;
+
+ // Sets the text visible in the omnibox.
+ bool SetText(const std::wstring& text);
+
+ // Determines if a query to an autocomplete provider is still in progress.
+ // NOTE: No autocomplete queries will be made if the omnibox doesn't have
+ // focus. This can be achieved by sending a IDC_FOCUS_LOCATION accelerator
+ // to the browser.
+ bool IsQueryInProgress(bool* query_in_progress) const;
+
+ // Gets a list of autocomplete matches that have been gathered so far.
+ bool GetAutocompleteMatches(Matches* matches) const;
+
+ // Waits for all queries to autocomplete providers to complete.
+ // |wait_timeout_ms| gives the number of milliseconds to wait for the query
+ // to finish. Returns false if IPC call failed or if the function times out.
+ bool WaitForQuery(int wait_timeout_ms) const;
+
+ private:
+ DISALLOW_EVIL_CONSTRUCTORS(AutocompleteEditProxy);
+};
+
+#endif // #define CHROME_TEST_AUTOMATION_AUTOCOMPLETE_EDIT_PROXY_H__
+
diff --git a/chrome/test/automation/automation.vcproj b/chrome/test/automation/automation.vcproj
new file mode 100644
index 0000000..38781fc
--- /dev/null
+++ b/chrome/test/automation/automation.vcproj
@@ -0,0 +1,193 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="automation"
+ ProjectGUID="{1556EF78-C7E6-43C8-951F-F6B43AC0DD12}"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ ConfigurationType="4"
+ InheritedPropertySheets="$(SolutionDir)..\build\debug.vsprops;.\automation.vsprops"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ ConfigurationType="4"
+ InheritedPropertySheets="$(SolutionDir)..\build\release.vsprops;.\automation.vsprops"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <File
+ RelativePath=".\autocomplete_edit_proxy.cc"
+ >
+ </File>
+ <File
+ RelativePath=".\autocomplete_edit_proxy.h"
+ >
+ </File>
+ <File
+ RelativePath=".\automation_constants.h"
+ >
+ </File>
+ <File
+ RelativePath=".\automation_handle_tracker.cc"
+ >
+ </File>
+ <File
+ RelativePath=".\automation_handle_tracker.h"
+ >
+ </File>
+ <File
+ RelativePath=".\automation_messages.h"
+ >
+ </File>
+ <File
+ RelativePath=".\automation_messages_internal.h"
+ >
+ </File>
+ <File
+ RelativePath=".\automation_proxy.cc"
+ >
+ </File>
+ <File
+ RelativePath=".\automation_proxy.h"
+ >
+ </File>
+ <File
+ RelativePath=".\browser_proxy.cc"
+ >
+ </File>
+ <File
+ RelativePath=".\browser_proxy.h"
+ >
+ </File>
+ <File
+ RelativePath=".\constrained_window_proxy.cc"
+ >
+ </File>
+ <File
+ RelativePath=".\constrained_window_proxy.h"
+ >
+ </File>
+ <File
+ RelativePath=".\tab_proxy.cc"
+ >
+ </File>
+ <File
+ RelativePath=".\tab_proxy.h"
+ >
+ </File>
+ <File
+ RelativePath=".\window_proxy.cc"
+ >
+ </File>
+ <File
+ RelativePath=".\window_proxy.h"
+ >
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/chrome/test/automation/automation.vsprops b/chrome/test/automation/automation.vsprops
new file mode 100644
index 0000000..4cc3b79
--- /dev/null
+++ b/chrome/test/automation/automation.vsprops
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioPropertySheet
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="automation"
+ InheritedPropertySheets="$(SolutionDir)..\build\common.vsprops;$(SolutionDir)..\skia\using_skia.vsprops"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+</VisualStudioPropertySheet>
diff --git a/chrome/test/automation/automation_constants.h b/chrome/test/automation/automation_constants.h
new file mode 100644
index 0000000..994d233
--- /dev/null
+++ b/chrome/test/automation/automation_constants.h
@@ -0,0 +1,38 @@
+// 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.
+
+#ifndef CHROME_TEST_AUTOMATION_AUTOMATION_CONSTANTS_H__
+#define CHROME_TEST_AUTOMATION_AUTOMATION_CONSTANTS_H__
+
+namespace automation {
+ // Amount of time to wait before querying the browser.
+ static const int kSleepTime = 250;
+}
+
+#endif // CHROME_TEST_AUTOMATION_AUTOMATION_CONSTANTS_H__ \ No newline at end of file
diff --git a/chrome/test/automation/automation_handle_tracker.cc b/chrome/test/automation/automation_handle_tracker.cc
new file mode 100644
index 0000000..a31d125
--- /dev/null
+++ b/chrome/test/automation/automation_handle_tracker.cc
@@ -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.
+
+#include "chrome/test/automation/automation_handle_tracker.h"
+
+#include "chrome/test/automation/automation_messages.h"
+#include "chrome/test/automation/automation_proxy.h"
+
+AutomationResourceProxy::AutomationResourceProxy(
+ AutomationHandleTracker* tracker, AutomationMessageSender* sender,
+ AutomationHandle handle)
+ : tracker_(tracker),
+ sender_(sender),
+ handle_(handle),
+ is_valid_(true) {
+ tracker_->Add(this);
+}
+
+AutomationResourceProxy::~AutomationResourceProxy() {
+ if (tracker_)
+ tracker_->Remove(this);
+}
+
+AutomationHandleTracker::~AutomationHandleTracker() {
+ // Tell any live objects that the tracker is going away so they don't try to
+ // call us when they are being destroyed.
+ for (HandleToObjectMap::iterator iter = handle_to_object_.begin();
+ iter != handle_to_object_.end(); ++iter) {
+ iter->second->Invalidate();
+ iter->second->TrackerGone();
+ }
+}
+
+void AutomationHandleTracker::Add(AutomationResourceProxy* proxy) {
+ handle_to_object_.insert(MapEntry(proxy->handle(), proxy));
+}
+
+void AutomationHandleTracker::Remove(AutomationResourceProxy* proxy) {
+ HandleToObjectMap::iterator iter = handle_to_object_.find(proxy->handle());
+ if (iter == handle_to_object_.end())
+ return;
+
+ HandleToObjectMap::iterator end_of_matching_objects =
+ handle_to_object_.upper_bound(proxy->handle());
+
+ while(iter != end_of_matching_objects) {
+ if (iter->second == proxy) {
+ handle_to_object_.erase(iter);
+
+ // If we have no more proxy objects using this handle, tell the
+ // app that it can clean up that handle. If the proxy isn't valid,
+ // that means that the app has already discarded this handle, and
+ // thus doesn't need to be notified that the handle is unused.
+ if (proxy->is_valid() && handle_to_object_.count(proxy->handle()) == 0) {
+ sender_->Send(new AutomationMsg_HandleUnused(0, proxy->handle()));
+ }
+ return;
+ }
+ ++iter;
+ }
+}
+
+void AutomationHandleTracker::InvalidateHandle(AutomationHandle handle) {
+ HandleToObjectMap::iterator iter = handle_to_object_.lower_bound(handle);
+ HandleToObjectMap::const_iterator end_of_matching_objects =
+ handle_to_object_.upper_bound(handle);
+
+ for (; iter != end_of_matching_objects; ++iter) {
+ iter->second->Invalidate();
+ }
+}
diff --git a/chrome/test/automation/automation_handle_tracker.h b/chrome/test/automation/automation_handle_tracker.h
new file mode 100644
index 0000000..8f064e3
--- /dev/null
+++ b/chrome/test/automation/automation_handle_tracker.h
@@ -0,0 +1,128 @@
+// 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.
+
+// This file defines a mapping between Automation Proxy objects and
+// their associated app-side handles.
+
+#ifndef CHROME_TEST_AUTOMATION_AUTOMATION_HANDLE_TRACKER_H__
+#define CHROME_TEST_AUTOMATION_AUTOMATION_HANDLE_TRACKER_H__
+
+#include <map>
+
+#include "base/basictypes.h"
+
+// This represents a value that the app's AutomationProvider returns
+// when asked for a resource (like a window or tab).
+typedef int AutomationHandle;
+
+class AutomationHandleTracker;
+class AutomationMessageSender;
+
+class AutomationResourceProxy {
+ public:
+ AutomationResourceProxy(AutomationHandleTracker* tracker,
+ AutomationMessageSender* sender,
+ AutomationHandle handle);
+ virtual ~AutomationResourceProxy();
+
+ // Marks this proxy object as no longer valid; this generally means
+ // that the corresponding resource on the app side is gone.
+ void Invalidate() { is_valid_ = false; }
+ bool is_valid() const { return is_valid_; }
+
+ // Returns the handle that the app has generated to refer to this resource.
+ AutomationHandle handle() { return handle_; }
+
+ protected:
+ friend class AutomationHandleTracker;
+
+ AutomationHandle handle_;
+
+ // Called by the tracker when it is being destroyed so we know not to call
+ // it back.
+ void TrackerGone() {
+ tracker_ = NULL;
+ }
+
+ // Not owned by us, owned by the AutomationProxy object. May be NULL if the
+ // tracker has been destroyed (and hence the object is invalid).
+ AutomationHandleTracker* tracker_;
+
+ // Not owned by us.
+ AutomationMessageSender* sender_;
+
+ private:
+ // True if the resource that this object is a proxy for on the app side
+ // still exists.
+ bool is_valid_;
+
+ DISALLOW_EVIL_CONSTRUCTORS(AutomationResourceProxy);
+};
+
+// This class keeps track of the mapping between AutomationHandles and
+// AutomationResourceProxy objects. This is important because (1) multiple
+// AutomationResourceProxy objects can be generated for the same handle
+// (2) handles can be invalidated by the app, and all the associated
+// proxy objects then need to be invalidated, and (3) when a handle is no
+// longer being used on this end, we need to tell the app that it can
+// discard the handle.
+class AutomationHandleTracker {
+ public:
+ AutomationHandleTracker(AutomationMessageSender* sender)
+ : sender_(sender) {}
+ ~AutomationHandleTracker();
+
+ // Adds the specified proxy object to the tracker.
+ void Add(AutomationResourceProxy* proxy);
+
+ // Removes a given proxy object from the mapping, and unregisters the
+ // handle on the app side if this was the last proxy object that was using
+ // that handle. This is a no-op if the proxy object is not currently
+ // in the tracker.
+ void Remove(AutomationResourceProxy* proxy);
+
+ // Marks all proxy objects related to a given handle invalid. This is
+ // used when a resource (like a window) on the app side is closed, meaning
+ // that no further operations can be completed using the handle that
+ // identified that resource.
+ void InvalidateHandle(AutomationHandle handle);
+
+ private:
+ typedef
+ std::multimap<AutomationHandle, AutomationResourceProxy*> HandleToObjectMap;
+ typedef std::pair<AutomationHandle, AutomationResourceProxy*> MapEntry;
+
+ HandleToObjectMap handle_to_object_;
+
+ AutomationMessageSender* sender_;
+
+ DISALLOW_EVIL_CONSTRUCTORS(AutomationHandleTracker);
+};
+
+#endif // CHROME_TEST_AUTOMATION_AUTOMATION_HANDLE_TRACKER_H__ \ No newline at end of file
diff --git a/chrome/test/automation/automation_messages.h b/chrome/test/automation/automation_messages.h
new file mode 100644
index 0000000..a106e38
--- /dev/null
+++ b/chrome/test/automation/automation_messages.h
@@ -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.
+
+#ifndef CHROME_TEST_AUTOMATION_AUTOMATION_MESSAGES_H__
+#define CHROME_TEST_AUTOMATION_AUTOMATION_MESSAGES_H__
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "chrome/common/ipc_message.h"
+#include "chrome/common/ipc_message_utils.h"
+
+enum AutomationMsg_NavigationResponseValues {
+ AUTOMATION_MSG_NAVIGATION_ERROR = 0,
+ AUTOMATION_MSG_NAVIGATION_SUCCESS,
+ AUTOMATION_MSG_NAVIGATION_AUTH_NEEDED,
+};
+
+// Two-pass include of render_messages_internal. Preprocessor magic allows
+// us to use 1 header to define the enums and classes for our render messages.
+#define IPC_MESSAGE_MACROS_ENUMS
+#include "chrome/test/automation/automation_messages_internal.h"
+
+#ifdef IPC_MESSAGE_MACROS_LOG_ENABLED
+# undef IPC_MESSAGE_MACROS_LOG
+# define IPC_MESSAGE_MACROS_CLASSES
+#include "chrome/test/automation/automation_messages_internal.h"
+
+# undef IPC_MESSAGE_MACROS_CLASSES
+# define IPC_MESSAGE_MACROS_LOG
+#include "chrome/test/automation/automation_messages_internal.h"
+#else
+// No debug strings requested, just define the classes
+# define IPC_MESSAGE_MACROS_CLASSES
+#include "chrome/test/automation/automation_messages_internal.h"
+#endif
+
+
+#endif // CHROME_TEST_AUTOMATION_AUTOMATION_MESSAGES_H__
diff --git a/chrome/test/automation/automation_messages_internal.h b/chrome/test/automation/automation_messages_internal.h
new file mode 100644
index 0000000..64ee503
--- /dev/null
+++ b/chrome/test/automation/automation_messages_internal.h
@@ -0,0 +1,723 @@
+// 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.
+
+// Defines the IPC messages used by the automation interface.
+
+// This header is meant to be included in multiple passes, hence no traditional
+// header guard.
+// See ipc_message_macros.h for explanation of the macros and passes.
+
+#include <string>
+#include <vector>
+
+#include "chrome/common/ipc_message_macros.h"
+#include "chrome/common/navigation_types.h"
+#include "chrome/test/automation/autocomplete_edit_proxy.h"
+
+// NOTE: All IPC messages have either a routing_id of 0 (for asynchronous
+// messages), or one that's been assigned by the proxy (for calls
+// which expect a response). The routing_id shouldn't be used for
+// any other purpose in these message types.
+
+// NOTE: All the new IPC messages should go at the end (before IPC_END_MESSAGES)
+// The IPC message IDs are part of an enum and hence the value
+// assumed to be constant across the builds may change.
+// The messages AutomationMsg_WindowHWND* in particular should not change
+// since the PageCyclerReferenceTest depend on the correctness of the
+// the message IDs across the builds.
+
+// By using a start value of 0 for automation messages, we keep backward
+// compatability with old builds.
+IPC_BEGIN_MESSAGES(Automation, 0)
+
+ // This message is fired when the AutomationProvider is up and running
+ // in the app (the app is not fully up at this point).
+ IPC_MESSAGE_ROUTED0(AutomationMsg_Hello)
+
+ // This message is fired when the initial tab(s) are finished loading.
+ IPC_MESSAGE_ROUTED0(AutomationMsg_InitialLoadsComplete)
+
+ // This message notifies the AutomationProvider to append a new tab the window
+ // with the given handle. The response contains the index of the new tab, or
+ // -1 if the request failed.
+ // The second parameter is the url to be loaded in the new tab.
+ IPC_MESSAGE_ROUTED2(AutomationMsg_AppendTabRequest, int, GURL)
+ IPC_MESSAGE_ROUTED1(AutomationMsg_AppendTabResponse, int)
+
+ // This message requests the (zero-based) index for the currently
+ // active tab in the window with the given handle. The response contains
+ // the index of the active tab, or -1 if the request failed.
+ IPC_MESSAGE_ROUTED1(AutomationMsg_ActiveTabIndexRequest, int)
+ IPC_MESSAGE_ROUTED1(AutomationMsg_ActiveTabIndexResponse, int)
+
+ // This message notifies the AutomationProvider to active the tab.
+ // The first parameter is the handle to window resource.
+ // The second parameter is the (zero-based) index to be activated
+ IPC_MESSAGE_ROUTED2(AutomationMsg_ActivateTabRequest, int, int)
+ IPC_MESSAGE_ROUTED1(AutomationMsg_ActivateTabResponse, int)
+
+ // This message requests the cookie value for given url in the
+ // profile of the tab identified by the second parameter. The first
+ // parameter is the URL string. The response contains the length of the cookie
+ // value string. On failure, this length = -1.
+ IPC_MESSAGE_ROUTED2(AutomationMsg_GetCookiesRequest, GURL, int)
+ IPC_MESSAGE_ROUTED2(AutomationMsg_GetCookiesResponse, int, std::string)
+
+ // This message notifies the AutomationProvider to set and broadcast a cookie
+ // with given name and value for the given url in the profile of the tab
+ // identified by the third parameter. The first parameter is the URL
+ // string, and the second parameter is the cookie name and value to be set.
+ // The response returns a non-negative value on success.
+ IPC_MESSAGE_ROUTED3(AutomationMsg_SetCookieRequest, GURL, std::string, int)
+ IPC_MESSAGE_ROUTED1(AutomationMsg_SetCookieResponse, int)
+
+ // This message notifies the AutomationProvider to navigate to a specified url
+ // in the tab with given handle. The first parameter is the handle to the tab
+ // resource. The second parameter is the target url. The response contains a
+ // status code which is nonnegative on success.
+ IPC_MESSAGE_ROUTED2(AutomationMsg_NavigateToURLRequest, int, GURL)
+ IPC_MESSAGE_ROUTED1(AutomationMsg_NavigateToURLResponse,
+ int) // see AutomationMsg_NavigationResponseValues
+
+ // This message is used to implement the asynchronous version of
+ // NavigateToURL.
+ IPC_MESSAGE_ROUTED2(AutomationMsg_NavigationAsyncRequest,
+ int /* tab handle */,
+ GURL)
+ IPC_MESSAGE_ROUTED1(AutomationMsg_NavigationAsyncResponse,
+ bool /* error value */)
+
+ // This message notifies the AutomationProvider to navigate back in session
+ // history in the tab with given handle. The first parameter is the handle
+ // to the tab resource. The response contains a status code which is
+ // nonnegative on success.
+ IPC_MESSAGE_ROUTED1(AutomationMsg_GoBackRequest, int)
+ IPC_MESSAGE_ROUTED1(AutomationMsg_GoBackResponse,
+ int) // see AutomationMsg_NavigationResponseValues
+
+ // This message notifies the AutomationProvider to navigate forward in session
+ // history in the tab with given handle. The first parameter is the handle
+ // to the tab resource. The response contains a status code which is
+ // nonnegative on success.
+ IPC_MESSAGE_ROUTED1(AutomationMsg_GoForwardRequest, int)
+ IPC_MESSAGE_ROUTED1(AutomationMsg_GoForwardResponse,
+ int) // see AutomationMsg_NavigationResponseValues
+
+ // This message requests the number of browser windows that the app currently
+ // has open. The parameter in the response is the number of windows.
+ IPC_MESSAGE_ROUTED0(AutomationMsg_BrowserWindowCountRequest)
+ IPC_MESSAGE_ROUTED1(AutomationMsg_BrowserWindowCountResponse, int)
+
+ // This message requests the handle (int64 app-unique identifier) of the
+ // window with the given (zero-based) index. On error, the returned handle
+ // value is 0.
+ IPC_MESSAGE_ROUTED1(AutomationMsg_BrowserWindowRequest, int)
+ IPC_MESSAGE_ROUTED1(AutomationMsg_BrowserWindowResponse, int)
+
+ // This message requests the number of tabs in the window with the given
+ // handle. The response contains the number of tabs, or -1 if the request
+ // failed.
+ IPC_MESSAGE_ROUTED1(AutomationMsg_TabCountRequest, int)
+ IPC_MESSAGE_ROUTED1(AutomationMsg_TabCountResponse, int)
+
+ // This message requests the handle of the tab with the given (zero-based)
+ // index in the given app window. First parameter specifies the given window
+ // handle, second specifies the given tab_index. On error, the returned handle
+ // value is 0.
+ IPC_MESSAGE_ROUTED2(AutomationMsg_TabRequest, int, int)
+ IPC_MESSAGE_ROUTED1(AutomationMsg_TabResponse, int)
+
+ // This message requests the the title of the tab with the given handle.
+ // The response contains the size of the title string. On error, this value
+ // should be -1 and empty string. Note that the title can be empty in which
+ // case the size would be 0.
+ IPC_MESSAGE_ROUTED1(AutomationMsg_TabTitleRequest, int)
+ IPC_MESSAGE_ROUTED2(AutomationMsg_TabTitleResponse, int, std::wstring)
+
+ // This message requests the the url of the tab with the given handle.
+ // The response contains a success flag and the URL string. The URL will
+ // be empty on failure, and it still may be empty on success.
+ IPC_MESSAGE_ROUTED1(AutomationMsg_TabURLRequest,
+ int /* tab handle */)
+ IPC_MESSAGE_ROUTED2(AutomationMsg_TabURLResponse,
+ bool /* success flag*/,
+ GURL)
+
+ // This message requests the HWND of the top-level window that corresponds
+ // to the given automation handle.
+ // The response contains the HWND value, which is 0 if the call fails.
+ IPC_MESSAGE_ROUTED1(AutomationMsg_WindowHWNDRequest,
+ int /* automation handle */)
+ IPC_MESSAGE_ROUTED1(AutomationMsg_WindowHWNDResponse,
+ HWND /* Win32 handle */)
+
+ // This message notifies the AutomationProxy that a handle that it has
+ // previously been given is now invalid. (For instance, if the handle
+ // represented a window which has now been closed.) The parameter
+ // value is the handle.
+ IPC_MESSAGE_ROUTED1(AutomationMsg_InvalidateHandle, int)
+
+ // This message notifies the AutomationProvider that a handle is no
+ // longer being used, so it can stop paying attention to the
+ // associated resource. The parameter value is the handle.
+ IPC_MESSAGE_ROUTED1(AutomationMsg_HandleUnused, int)
+
+ // This message requests the HWND of the tab that corresponds
+ // to the given automation handle.
+ // The response contains the HWND value, which is 0 if the call fails.
+ IPC_MESSAGE_ROUTED1(AutomationMsg_TabHWNDRequest,
+ int /* tab_handle */)
+ IPC_MESSAGE_ROUTED1(AutomationMsg_TabHWNDResponse,
+ HWND /* win32 Window Handle*/)
+
+ // This message tells the AutomationProvider to provide the given
+ // authentication data to the specified tab, in response to an HTTP/FTP
+ // authentication challenge.
+ // The response status will be negative on error.
+ IPC_MESSAGE_ROUTED3(AutomationMsg_SetAuthRequest,
+ int, // tab handle
+ std::wstring, // username
+ std::wstring) // password
+ IPC_MESSAGE_ROUTED1(AutomationMsg_SetAuthResponse,
+ int) // status
+
+ // This message tells the AutomationProvider to cancel the login in the
+ // specified tab.
+ // The response status will be negative on error.
+ IPC_MESSAGE_ROUTED1(AutomationMsg_CancelAuthRequest,
+ int) // tab handle
+ IPC_MESSAGE_ROUTED1(AutomationMsg_CancelAuthResponse,
+ int) // status
+
+ // Requests that the automation provider ask history for the most recent
+ // chain of redirects coming from the given URL. The response must be
+ // decoded by the caller manually; it contains an integer indicating the
+ // number of URLs, followed by that many wstrings indicating a chain of
+ // redirects. On failure, the count will be negative.
+ IPC_MESSAGE_ROUTED2(AutomationMsg_RedirectsFromRequest,
+ int, // tab handle
+ GURL) // source URL
+ IPC_MESSAGE_EMPTY(AutomationMsg_RedirectsFromResponse)
+
+ // This message asks the AutomationProvider whether a tab is waiting for
+ // login info.
+ IPC_MESSAGE_ROUTED1(AutomationMsg_NeedsAuthRequest,
+ int) // tab handle
+ IPC_MESSAGE_ROUTED1(AutomationMsg_NeedsAuthResponse,
+ bool) // status
+
+ // This message requests the AutomationProvider to apply a certain
+ // accelerator. It is completely asynchronous with the resulting accelerator
+ // action.
+ IPC_MESSAGE_ROUTED2(AutomationMsg_ApplyAcceleratorRequest,
+ int, // window handle
+ int) // accelerator id like (IDC_BACK, IDC_FORWARD ...)
+ // The list can be found at
+ // chrome/app/chrome_dll_resource.h
+
+ // This message requests that the AutomationProvider executes a JavaScript,
+ // which is sent embedded in a 'javascript:' URL.
+ // The javascript is executed in context of child frame whose xpath
+ // is passed as parameter (context_frame). The execution results in
+ // a serialized JSON string response.
+ IPC_MESSAGE_ROUTED3(AutomationMsg_DomOperationRequest,
+ int, // tab handle
+ std::wstring, // context_frame
+ std::wstring) // the javascript to be executed
+
+ // This message is used to communicate the values received by the
+ // callback binding the JS to Cpp. This message forms the second leg in
+ // the communication channel. The values are originally received in the
+ // renderer which are then sent to the app (wrapped as json) using
+ // corresponding message in render_messages_internal.h
+ // This message simply relays the json string.
+ IPC_MESSAGE_ROUTED1(AutomationMsg_DomOperationResponse,
+ std::string) // the serialized json string containing
+ // the result of a javascript execution
+
+ // Is the Download Shelf visible for the specified tab?
+ IPC_MESSAGE_ROUTED1(AutomationMsg_ShelfVisibilityRequest,
+ int /* tab_handle */)
+ IPC_MESSAGE_ROUTED1(AutomationMsg_ShelfVisibilityResponse,
+ bool /* is_visible */)
+
+ // This message requests the number of constrained windows in the tab with
+ // the given handle. The response contains the number of constrained windows,
+ // or -1 if the request failed.
+ IPC_MESSAGE_ROUTED1(AutomationMsg_ConstrainedWindowCountRequest,
+ int /* tab_handle */)
+ IPC_MESSAGE_ROUTED1(AutomationMsg_ConstrainedWindowCountResponse,
+ int /* constrained_window_count */)
+
+ // This message requests the handle of the constrained window with the given
+ // (zero-based) index in the given tab. First parameter specifies the given
+ // tab handle, second specifies the given child_index. On error, the returned
+ // handle value is 0.
+ IPC_MESSAGE_ROUTED2(AutomationMsg_ConstrainedWindowRequest,
+ int, /* window_handle */
+ int) /* child_index */
+
+ IPC_MESSAGE_ROUTED1(AutomationMsg_ConstrainedWindowResponse,
+ int) /* constrained_handle */
+
+ // This message requests the the title of the constrained window with the
+ // given handle. The response contains the size of the title string and title
+ // string. On error, this value should be -1 and empty string. Note that the
+ // title can be empty in which case the size would be 0.
+ IPC_MESSAGE_ROUTED1(AutomationMsg_ConstrainedTitleRequest, int)
+ IPC_MESSAGE_ROUTED2(AutomationMsg_ConstrainedTitleResponse, int, std::wstring)
+
+ // This message requests the bounds of the specified View element in
+ // window coordinates.
+ // Request:
+ // int - the handle of the window in which the view appears
+ // int - the ID of the view, as specified in chrome/browser/view_ids.h
+ // bool - whether the bounds should be returned in the screen coordinates
+ // (if true) or in the browser coordinates (if false).
+ // Response:
+ // bool - true if the view was found
+ // gfx::Rect - the bounds of the view, in window coordinates
+ IPC_MESSAGE_ROUTED3(AutomationMsg_WindowViewBoundsRequest, int, int, bool)
+ IPC_MESSAGE_ROUTED2(AutomationMsg_WindowViewBoundsResponse, bool, gfx::Rect)
+
+ // This message requests that a drag be performed in window coordinate space
+ // Request:
+ // int - the handle of the window that's the context for this drag
+ // std::vector<POINT> - the path of the drag in window coordinate space;
+ // it should have at least 2 points (start and end)
+ // int - the flags which identify the mouse button(s) for the drag, as
+ // defined in chrome/views/event.h
+ // Response:
+ // bool - true if the drag could be performed
+ IPC_MESSAGE_ROUTED3(AutomationMsg_WindowDragRequest,
+ int, std::vector<POINT>, int)
+ IPC_MESSAGE_ROUTED1(AutomationMsg_WindowDragResponse, bool)
+
+ // Similar to AutomationMsg_InitialLoadsComplete, this indicates that the
+ // new tab ui has completed the initial load of its data.
+ // Time is how many milliseconds the load took.
+ IPC_MESSAGE_ROUTED1(AutomationMsg_InitialNewTabUILoadComplete,
+ int /* time */)
+
+ // This message starts a find within a tab corresponding to the supplied
+ // tab handle. The response contains the number of matches found on the page
+ // within the tab specified. The parameter 'search_string' specifies what
+ // string to search for, 'forward' specifies whether to search in forward
+ // direction (1=forward, 0=back), 'match_case' specifies case sensitivity
+ // (1=case sensitive, 0=case insensitive). If an error occurs, matches_found
+ // will be -1.
+ IPC_MESSAGE_ROUTED4(AutomationMsg_FindInPageRequest,
+ int, /* tab_handle */
+ std::wstring, /* find_request */
+ int, /* forward */
+ int /* match_case */)
+ IPC_MESSAGE_ROUTED1(AutomationMsg_FindInPageResponse,
+ int /* matches_found */)
+
+ // This message sends a inspect element request for a given tab. The response
+ // contains the number of resources loaded by the inspector controller.
+ IPC_MESSAGE_ROUTED3(AutomationMsg_InspectElementRequest,
+ int, /* tab_handle */
+ int, /* x */
+ int /* y */)
+ IPC_MESSAGE_ROUTED1(AutomationMsg_InspectElementResponse, int)
+
+ // This message requests the process ID of the tab that corresponds
+ // to the given automation handle.
+ // The response has an integer corresponding to the PID of the tab's
+ // renderer, 0 if the tab currently has no renderer process, or -1 on error.
+ IPC_MESSAGE_ROUTED1(AutomationMsg_TabProcessIDRequest,
+ int /* tab_handle */)
+ IPC_MESSAGE_ROUTED1(AutomationMsg_TabProcessIDResponse,
+ int /* process ID */)
+
+ // This tells the browser to enable or disable the filtered network layer.
+ IPC_MESSAGE_ROUTED1(AutomationMsg_SetFilteredInet,
+ bool /* enabled */)
+
+ // Gets the directory that downloads will occur in for the active profile.
+ IPC_MESSAGE_ROUTED1(AutomationMsg_DownloadDirectoryRequest,
+ int /* tab_handle */)
+ IPC_MESSAGE_ROUTED1(AutomationMsg_DownloadDirectoryResponse,
+ std::wstring /* directory */)
+
+ // This message requests the id of the view that has the focus in the
+ // specified window. If no view is focused, -1 is returned. Note that the
+ // window should either be a ViewWindow or a Browser.
+ IPC_MESSAGE_ROUTED1(AutomationMsg_GetFocusedViewIDRequest,
+ int /* view_handle */)
+ IPC_MESSAGE_ROUTED1(AutomationMsg_GetFocusedViewIDResponse,
+ int /* focused_view_id */)
+
+ // This message shows/hides the window.
+ IPC_MESSAGE_ROUTED2(AutomationMsg_SetWindowVisibleRequest,
+ int /* view_handle */, bool /* visible */)
+ IPC_MESSAGE_ROUTED1(AutomationMsg_SetWindowVisibleResponse,
+ bool /* success */)
+
+ // Gets the active status of a window.
+ IPC_MESSAGE_ROUTED1(AutomationMsg_IsWindowActiveRequest,
+ int /* view_handle */)
+ IPC_MESSAGE_ROUTED2(AutomationMsg_IsWindowActiveResponse,
+ bool /* success */, bool /* active */)
+
+ // Makes the specified window the active window.
+ IPC_MESSAGE_ROUTED1(AutomationMsg_ActivateWindow, int /* view_handle */)
+
+ // Opens a new browser window.
+ IPC_MESSAGE_ROUTED1(AutomationMsg_OpenNewBrowserWindow,
+ int /* show_command*/ )
+
+ // This message requests the handle (int64 app-unique identifier) of the
+ // current active top window. On error, the returned handle value is 0.
+ IPC_MESSAGE_ROUTED0(AutomationMsg_ActiveWindowRequest)
+ IPC_MESSAGE_ROUTED1(AutomationMsg_ActiveWindowResponse, int)
+
+ // This message requests the browser associated with the specified window
+ // handle.
+ // The response contains a success flag and the handle of the browser.
+ IPC_MESSAGE_ROUTED1(AutomationMsg_BrowserForWindowRequest,
+ int /* window handle */)
+ IPC_MESSAGE_ROUTED2(AutomationMsg_BrowserForWindowResponse,
+ bool /* success flag */,
+ int /* browser handle */)
+
+ // This message requests the window associated with the specified browser
+ // handle.
+ // The response contains a success flag and the handle of the window.
+ IPC_MESSAGE_ROUTED1(AutomationMsg_WindowForBrowserRequest,
+ int /* browser handle */)
+ IPC_MESSAGE_ROUTED2(AutomationMsg_WindowForBrowserResponse,
+ bool /* success flag */,
+ int /* window handle */)
+
+ // This message requests the AutocompleteEdit associated with the specified
+ // browser handle.
+ // The response contains a success flag and the handle of the omnibox.
+ IPC_MESSAGE_ROUTED1(AutomationMsg_AutocompleteEditForBrowserRequest,
+ int /* browser handle */)
+ IPC_MESSAGE_ROUTED2(AutomationMsg_AutocompleteEditForBrowserResponse,
+ bool /* success flag */,
+ int /* AutocompleteEdit handle */)
+
+ // This message requests that a mouse click be performed in window coordinate
+ // space.
+ // Request:
+ // int - the handle of the window that's the context for this click
+ // POINT - the point to click
+ // int - the flags which identify the mouse button(s) for the click, as
+ // defined in chrome/views/event.h
+ IPC_MESSAGE_ROUTED3(AutomationMsg_WindowClickRequest, int, POINT, int)
+
+ // This message requests that a key press be performed.
+ // Request:
+ // int - the handle of the window that's the context for this click
+ // wchar_t - char of the key that was pressed.
+ // int - the flags which identify the modifiers (shift, ctrl, alt)
+ // associated for, as defined in chrome/views/event.h
+ IPC_MESSAGE_ROUTED3(AutomationMsg_WindowKeyPressRequest, int, wchar_t, int)
+
+ // This message notifies the AutomationProvider to create a tab which is
+ // hosted by an external process. The response contains the HWND of the
+ // window that contains the external tab and the handle to the newly
+ // created tab
+ // The second parameter is the url to be loaded in the new tab.
+ IPC_MESSAGE_ROUTED0(AutomationMsg_CreateExternalTab)
+ IPC_MESSAGE_ROUTED2(AutomationMsg_CreateExternalTabResponse, HWND, int)
+
+ // This message notifies the AutomationProvider to navigate to a specified
+ // url in the external tab with given handle. The first parameter is the
+ // handle to the tab resource. The second parameter is the target url.
+ // The response contains a status code which is nonnegative on success.
+ IPC_MESSAGE_ROUTED2(AutomationMsg_NavigateInExternalTabRequest, int, GURL)
+ IPC_MESSAGE_ROUTED1(AutomationMsg_NavigateInExternalTabResponse,
+ int) // see AutomationMsg_NavigationResponseValues
+
+ // This message is an outgoing message from Chrome to an external host.
+ // It is a notification that the NavigationState was changed
+ // Request:
+ // -int: The flags specifying what changed
+ // (see TabContents::InvalidateTypes)
+ // Response:
+ // None expected
+ IPC_MESSAGE_ROUTED1(AutomationMsg_NavigationStateChanged, int)
+
+ // This message is an outgoing message from Chrome to an external host.
+ // It is a notification that the target URL has changed (the target URL
+ // is the URL of the link that the user is hovering on)
+ // Request:
+ // -std::wstring: The new target URL
+ // Response:
+ // None expected
+ IPC_MESSAGE_ROUTED1(AutomationMsg_UpdateTargetUrl, std::wstring)
+
+ // This message notifies the AutomationProvider to show the specified html
+ // text in an interstitial page in the tab with given handle. The first
+ // parameter is the handle to the tab resource. The second parameter is the
+ // html text to be displayed.
+ // The response contains a success flag.
+ IPC_MESSAGE_ROUTED2(AutomationMsg_ShowInterstitialPageRequest,
+ int,
+ std::string)
+ IPC_MESSAGE_ROUTED1(AutomationMsg_ShowInterstitialPageResponse, bool)
+
+ // This message notifies the AutomationProvider to hide the current
+ // interstitial page in the tab with given handle. The parameter is the handle
+ // to the tab resource.
+ // The response contains a success flag.
+ IPC_MESSAGE_ROUTED1(AutomationMsg_HideInterstitialPageRequest, int)
+ IPC_MESSAGE_ROUTED1(AutomationMsg_HideInterstitialPageResponse, bool)
+
+ // This message requests that a tab be closed.
+ // Request:
+ // - int: handle of the tab to close
+ // - bool: if true the proxy blocks until the tab has completely closed,
+ // otherwise the proxy only blocks until it initiates the close.
+ IPC_MESSAGE_ROUTED2(AutomationMsg_CloseTabRequest, int, bool)
+ IPC_MESSAGE_ROUTED1(AutomationMsg_CloseTabResponse, bool)
+
+ // This message requests that the browser be closed.
+ // Request:
+ // - int: handle of the browser which contains the tab
+ // Response:
+ // - bool: whether the operation was successfull.
+ // - bool: whether the browser process will be terminated as a result (if
+ // this was the last closed browser window).
+ IPC_MESSAGE_ROUTED1(AutomationMsg_CloseBrowserRequest, int)
+ IPC_MESSAGE_ROUTED2(AutomationMsg_CloseBrowserResponse, bool, bool)
+
+ // This message sets the keyboard accelarators to be used by an externally
+ // hosted tab. This call is not valid on a regular tab hosted within
+ // Chrome.
+ // Request:
+ // - int: handle of the tab
+ // - HACCEL: The accelerator table to be set
+ // - int: The number of entries in the accelerator table
+ // Response:
+ // -bool: whether the operation was successful.
+ IPC_MESSAGE_ROUTED3(AutomationMsg_SetAcceleratorsForTab, int, HACCEL, int)
+ IPC_MESSAGE_ROUTED1(AutomationMsg_SetAcceleratorsForTabResponse, bool)
+
+ // This message is an outgoing message from Chrome to an external host.
+ // It is a request to process a keyboard accelerator.
+ // Request:
+ // -MSG: The keyboard message
+ // Response:
+ // None expected
+ // TODO(sanjeevr): Ideally we need to add a response from the external
+ // host saying whether it processed the accelerator
+ IPC_MESSAGE_ROUTED1(AutomationMsg_HandleAccelerator, MSG)
+
+ // This message is an outgoing message from Chrome to an external host.
+ // It is a request to open a url
+ // Request:
+ // -GURL: The URL to open
+ // -int: The WindowOpenDisposition that specifies where the URL should
+ // be opened (new tab, new window etc).
+ // Response:
+ // None expected
+ IPC_MESSAGE_ROUTED2(AutomationMsg_OpenURL, GURL, int)
+
+ // This message is sent by the container of an externally hosted tab to
+ // reflect any accelerator keys that it did not process. This gives the
+ // tab a chance to handle the keys
+ // Request:
+ // - int: handle of the tab
+ // -MSG: The keyboard message that the container did not handle
+ // Response:
+ // None expected
+ IPC_MESSAGE_ROUTED2(AutomationMsg_ProcessUnhandledAccelerator, int, MSG)
+
+ // This message requests the provider to wait until the specified tab has
+ // finished restoring after session restore.
+ // Request:
+ // - int: handle of the tab
+ // Response:
+ // - bool: whether the operation was successful.
+ IPC_MESSAGE_ROUTED1(AutomationMsg_WaitForTabToBeRestored, int)
+
+ // Sent in response to AutomationMsg_WaitForTabToBeRestored once the tab has
+ // finished loading.
+ IPC_MESSAGE_ROUTED0(AutomationMsg_TabFinishedRestoring)
+
+ // This message is an outgoing message from Chrome to an external host.
+ // It is a notification that a navigation happened
+ // Request:
+ // -int : Indicates the type of navigation (see the NavigationType enum)
+ // -int: If this was not a new navigation, then this value indicates the
+ // relative offset of the navigation. A positive offset means a
+ // forward navigation, a negative value means a backward navigation
+ // and 0 means this was a redirect
+ // Response:
+ // None expected
+ IPC_MESSAGE_ROUTED2(AutomationMsg_DidNavigate, int, int)
+
+ // This message requests the different security states of the page displayed
+ // in the specified tab.
+ // Request:
+ // - int: handle of the tab
+ // Response:
+ // - bool: whether the operation was successful.
+ // - int: the security style of the tab (enum SecurityStyle see
+ // security_style.h)).
+ // - int: the status of the server's ssl cert (0 means no errors or no ssl
+ // was used).
+ // - int: the mixed content state, 0 means no mixed/unsafe contents.
+ IPC_MESSAGE_ROUTED1(AutomationMsg_GetSecurityState, int)
+ IPC_MESSAGE_ROUTED4(AutomationMsg_GetSecurityStateResponse,
+ bool,
+ int,
+ int,
+ int)
+
+ // This message requests the page type of the page displayed in the specified
+ // tab (normal, error or interstitial).
+ // Request:
+ // - int: handle of the tab
+ // Response:
+ // - bool: whether the operation was successful.
+ // - int: the type of the page currently displayed (enum PageType see
+ // entry_navigation.h).
+ IPC_MESSAGE_ROUTED1(AutomationMsg_GetPageType, int)
+ IPC_MESSAGE_ROUTED2(AutomationMsg_GetPageTypeResponse, bool, int)
+
+ // This message simulates the user action on the SSL blocking page showing in
+ // the specified tab. This message is only effective if an interstitial page
+ // is showing in the tab.
+ // Request:
+ // - int: handle of the tab
+ // - bool: whether to proceed or abort the navigation
+ // Response:
+ // - bool: whether the operation was successful.
+ IPC_MESSAGE_ROUTED2(AutomationMsg_ActionOnSSLBlockingPage, int, bool)
+ IPC_MESSAGE_ROUTED1(AutomationMsg_ActionOnSSLBlockingPageResponse, bool)
+
+ // Message to request that a browser window is brought to the front and activated.
+ // Request:
+ // - int: handle of the browser window.
+ // Response:
+ // - bool: True if the browser is brought to the front.
+ IPC_MESSAGE_ROUTED1(AutomationMsg_BringBrowserToFront, int)
+ IPC_MESSAGE_ROUTED1(AutomationMsg_BringBrowserToFrontResponse, bool)
+
+ // Message to request whether a certain item is enabled of disabled in the "Page"
+ // menu in the browser window
+ //
+ // Request:
+ // - int: handle of the browser window.
+ // - int: IDC message identifier to query if enabled
+ // Response:
+ // - bool: True if the command is enabled on the Page menu
+ IPC_MESSAGE_ROUTED2(AutomationMsg_IsPageMenuCommandEnabled, int, int)
+ IPC_MESSAGE_ROUTED1(AutomationMsg_IsPageMenuCommandEnabledResponse, bool)
+
+ // This message notifies the AutomationProvider to print the tab with given
+ // handle. The first parameter is the handle to the tab resource. The
+ // response contains a bool which is true on success.
+ IPC_MESSAGE_ROUTED1(AutomationMsg_PrintNowRequest, int)
+ IPC_MESSAGE_ROUTED1(AutomationMsg_PrintNowResponse, bool)
+
+ // This message notifies the AutomationProvider to reload the current page in
+ // the tab with given handle. The first parameter is the handle to the tab
+ // resource. The response contains a status code which is nonnegative on
+ // success.
+ IPC_MESSAGE_ROUTED1(AutomationMsg_ReloadRequest, int)
+ IPC_MESSAGE_ROUTED1(AutomationMsg_ReloadResponse,
+ int) // see AutomationMsg_NavigationResponseValues
+
+ // This message requests the handle (int64 app-unique identifier) of the
+ // last active browser window, or the browser at index 0 if there is no last
+ // active browser, or it no longer exists. Returns 0 if no browser windows
+ // exist.
+ IPC_MESSAGE_ROUTED0(AutomationMsg_LastActiveBrowserWindowRequest)
+ IPC_MESSAGE_ROUTED1(AutomationMsg_LastActiveBrowserWindowResponse, int)
+
+ // This message requests the bounds of a constrained window (relative to its
+ // containing TabContents). On an internal error, the boolean in the result will
+ // be set to false.
+ IPC_MESSAGE_ROUTED1(AutomationMsg_ConstrainedWindowBoundsRequest,
+ int /* tab_handle */)
+ IPC_MESSAGE_ROUTED2(AutomationMsg_ConstrainedWindowBoundsResponse,
+ bool /* the requested window exists */,
+ gfx::Rect /* constrained_window_count */)
+
+ // This message notifies the AutomationProvider to save the page with given
+ // handle. The first parameter is the handle to the tab resource. The second
+ // parameter is the main HTML file name. The third parameter is the directory
+ // for saving resources. The fourth parameter is the saving type: 0 for HTML
+ // only; 1 for complete web page.
+ // The response contains a bool which is true on success.
+ IPC_MESSAGE_ROUTED4(AutomationMsg_SavePageRequest, int, std::wstring,
+ std::wstring, int)
+ IPC_MESSAGE_ROUTED1(AutomationMsg_SavePageResponse, bool)
+
+
+ // This message requests the text currently being displayed in the
+ // AutocompleteEdit. The parameter is the handle to the AutocompleteEdit.
+ // The response is a string indicating the text in the AutocompleteEdit.
+ IPC_MESSAGE_ROUTED1(AutomationMsg_AutocompleteEditGetTextRequest,
+ int /* autocomplete edit handle */)
+ IPC_MESSAGE_ROUTED2(AutomationMsg_AutocompleteEditGetTextResponse,
+ bool /* the requested autocomplete edit exists */,
+ std::wstring /* omnibox text */)
+
+ // This message sets the text being displayed in the AutocompleteEdit. The
+ // first parameter is the handle to the omnibox and the second parameter is
+ // the text to be displayed in the AutocompleteEdit.
+ // The response has no parameters and is returned when the operation has
+ // completed.
+ IPC_MESSAGE_ROUTED2(AutomationMsg_AutocompleteEditSetTextRequest,
+ int /* autocomplete edit handle */,
+ std::wstring /* text to set */)
+ IPC_MESSAGE_ROUTED1(AutomationMsg_AutocompleteEditSetTextResponse,
+ bool /* the requested autocomplete edit exists */)
+
+ // This message requests if a query to a autocomplete provider is still in
+ // progress. The first parameter in the request is the handle to the
+ // autocomplete edit.
+ // The first parameter in the response indicates if the request succeeded.
+ // The second parameter in indicates if a query is still in progress.
+ IPC_MESSAGE_ROUTED1(AutomationMsg_AutocompleteEditIsQueryInProgressRequest,
+ int /* autocomplete edit handle*/)
+ IPC_MESSAGE_ROUTED2(AutomationMsg_AutocompleteEditIsQueryInProgressResponse,
+ bool /* the requested autocomplete edit exists */,
+ bool /* indicates if a query is in progress */)
+
+ // This message requests a list of the autocomplete messages currently being
+ // displayed by the popup. The parameter in the request is a handle to the
+ // autocomplete edit.
+ // The first parameter in the response indicates if the request was
+ // successful while the second parameter is the actual list of matches.
+ IPC_MESSAGE_ROUTED1(AutomationMsg_AutocompleteEditGetMatchesRequest,
+ int /* autocomplete edit handle*/)
+ IPC_MESSAGE_ROUTED2(AutomationMsg_AutocompleteEditGetMatchesResponse,
+ bool /* the requested autocomplete edit exists */,
+ std::vector<AutocompleteMatchData> /* matches */)
+
+IPC_END_MESSAGES(Automation)
diff --git a/chrome/test/automation/automation_proxy.cc b/chrome/test/automation/automation_proxy.cc
new file mode 100644
index 0000000..07e5387
--- /dev/null
+++ b/chrome/test/automation/automation_proxy.cc
@@ -0,0 +1,567 @@
+// 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.
+
+#include <sstream>
+
+#include "chrome/test/automation/automation_proxy.h"
+
+#include "base/logging.h"
+#include "base/ref_counted.h"
+#include "chrome/common/ipc_message_macros.h"
+#include "chrome/test/automation/autocomplete_edit_proxy.h"
+#include "chrome/test/automation/automation_constants.h"
+#include "chrome/test/automation/automation_messages.h"
+#include "chrome/test/automation/browser_proxy.h"
+#include "chrome/test/automation/tab_proxy.h"
+#include "chrome/test/automation/window_proxy.h"
+
+// This class exists to group together the data and functionality used for
+// synchronous automation requests.
+class AutomationRequest :
+ public base::RefCountedThreadSafe<AutomationRequest> {
+public:
+ AutomationRequest() {
+ static int32 routing_id = 0;
+ routing_id_ = ++routing_id;
+ received_response_ = ::CreateEvent(NULL, TRUE, FALSE, NULL);
+ DCHECK(received_response_);
+ }
+ ~AutomationRequest() {
+ DCHECK(received_response_);
+ ::CloseHandle(received_response_);
+ }
+
+ // This is called on the foreground thread to block while waiting for a
+ // response from the app.
+ // The function returns true if response is received, and returns false
+ // if there is a failure or timeout.
+ bool WaitForResponse(uint32 timeout_ms, bool* is_timeout) {
+ uint32 result = ::WaitForSingleObject(received_response_, timeout_ms);
+ if (is_timeout)
+ *is_timeout = (result == WAIT_TIMEOUT);
+
+ return result != WAIT_FAILED && result != WAIT_TIMEOUT;
+ }
+
+ // This is called on the background thread once the response has been
+ // received and the foreground thread can resume execution.
+ bool SignalResponseReady(const IPC::Message& response) {
+ response_.reset(new IPC::Message(response));
+
+ DCHECK(received_response_);
+ return !!::SetEvent(received_response_);
+ }
+
+ // This can be used to take ownership of the response object that
+ // we've received, reducing the need to copy the message.
+ void GrabResponse(IPC::Message** response) {
+ DCHECK(response);
+ *response = response_.get();
+ response_.release();
+ }
+
+ int32 routing_id() { return routing_id_; }
+
+ const IPC::Message& response() {
+ DCHECK(response_.get());
+ return *(response_.get());
+ }
+
+private:
+ DISALLOW_EVIL_CONSTRUCTORS(AutomationRequest);
+
+ int32 routing_id_;
+ scoped_ptr<IPC::Message> response_;
+ HANDLE received_response_;
+};
+
+namespace {
+
+// This object allows messages received on the background thread to be
+// properly triaged.
+class AutomationMessageFilter : public IPC::ChannelProxy::MessageFilter {
+ public:
+ AutomationMessageFilter(AutomationProxy* server) : server_(server) {}
+
+ // Return true to indicate that the message was handled, or false to let
+ // the message be handled in the default way.
+ virtual bool OnMessageReceived(const IPC::Message& message) {
+ {
+ // Here we're checking to see if it matches the (because there should
+ // be at most one) synchronous request. If the received message is
+ // the response to the synchronous request, we clear the server's
+ // "current_request" pointer and signal to the request object that
+ // the response is ready for processing. We're clearing current_request
+ // here rather than on the foreground thread so that we can assert
+ // that both threads perceive it as cleared at the time that the
+ // foreground thread wakes up.
+ scoped_refptr<AutomationRequest> request = server_->current_request();
+ if (request.get() && (message.routing_id() == request->routing_id())) {
+ server_->clear_current_request();
+ request->SignalResponseReady(message);
+ return true;
+ }
+ if (message.routing_id() > 0) {
+ // The message is either the previous async response or arrived
+ // after timeout.
+ return true;
+ }
+ }
+
+ bool handled = true;
+
+ IPC_BEGIN_MESSAGE_MAP(AutomationMessageFilter, message)
+ IPC_MESSAGE_HANDLER_GENERIC(
+ AutomationMsg_Hello, server_->SignalAppLaunch());
+ IPC_MESSAGE_HANDLER_GENERIC(
+ AutomationMsg_InitialLoadsComplete, server_->SignalInitialLoads());
+ IPC_MESSAGE_HANDLER(AutomationMsg_InitialNewTabUILoadComplete,
+ NewTabLoaded);
+ IPC_MESSAGE_HANDLER_GENERIC(
+ AutomationMsg_InvalidateHandle, server_->InvalidateHandle(message));
+ IPC_MESSAGE_UNHANDLED(handled = false);
+ IPC_END_MESSAGE_MAP()
+
+ return handled;
+ }
+
+ void NewTabLoaded(int load_time) {
+ server_->SignalNewTabUITab(load_time);
+ }
+
+ private:
+ AutomationProxy* server_;
+};
+
+} // anonymous namespace
+
+
+const int AutomationProxy::kMaxCommandExecutionTime = 30000;
+
+AutomationProxy::AutomationProxy() : current_request_(NULL) {
+ InitializeEvents();
+ InitializeChannelID();
+ InitializeThread();
+ InitializeChannel();
+ InitializeHandleTracker();
+}
+
+AutomationProxy::~AutomationProxy() {
+}
+
+void AutomationProxy::InitializeEvents() {
+ app_launched_ =
+ CreateEvent(NULL, // Handle cannot be inherited by child processes.
+ TRUE, // No automatic reset after a waiting thread released.
+ FALSE, // Initially not signalled.
+ NULL); // No name.
+ DCHECK(app_launched_);
+
+ // See the above call to CreateEvent to understand these parameters.
+ initial_loads_complete_ = CreateEvent(NULL, TRUE, FALSE, NULL);
+ DCHECK(initial_loads_complete_);
+
+ // See the above call to CreateEvent to understand these parameters.
+ new_tab_ui_load_complete_ = CreateEvent(NULL, TRUE, FALSE, NULL);
+ DCHECK(new_tab_ui_load_complete_);
+}
+
+void AutomationProxy::InitializeChannelID() {
+ // The channel counter keeps us out of trouble if we create and destroy
+ // several AutomationProxies sequentially over the course of a test run.
+ // (Creating the channel sometimes failed before when running a lot of
+ // tests in sequence, and our theory is that sometimes the channel ID
+ // wasn't getting freed up in time for the next test.)
+ static int channel_counter = 0;
+
+ std::wostringstream buf;
+ buf << L"ChromeTestingInterface:" << GetCurrentProcessId() <<
+ L"." << ++channel_counter;
+ channel_id_ = buf.str();
+}
+
+void AutomationProxy::InitializeThread() {
+ scoped_ptr<Thread> thread(new Thread("AutomationProxy_BackgroundThread"));
+ bool thread_result = thread->Start();
+ DCHECK(thread_result);
+ thread_.swap(thread);
+}
+
+void AutomationProxy::InitializeChannel() {
+ channel_.reset(new IPC::ChannelProxy(
+ channel_id_,
+ IPC::Channel::MODE_SERVER,
+ this, // we are the listener
+ new AutomationMessageFilter(this),
+ thread_->message_loop()));
+}
+
+void AutomationProxy::InitializeHandleTracker() {
+ tracker_.reset(new AutomationHandleTracker(this));
+}
+
+bool AutomationProxy::WaitForAppLaunch() {
+ return ::WaitForSingleObject(app_launched_,
+ kMaxCommandExecutionTime) == WAIT_OBJECT_0;
+}
+
+void AutomationProxy::SignalAppLaunch() {
+ ::SetEvent(app_launched_);
+}
+
+bool AutomationProxy::WaitForInitialLoads() {
+ return ::WaitForSingleObject(initial_loads_complete_,
+ kMaxCommandExecutionTime) == WAIT_OBJECT_0;
+}
+
+bool AutomationProxy::WaitForInitialNewTabUILoad(int* load_time) {
+ if (::WaitForSingleObject(new_tab_ui_load_complete_,
+ kMaxCommandExecutionTime) == WAIT_OBJECT_0) {
+ *load_time = new_tab_ui_load_time_;
+ ::ResetEvent(new_tab_ui_load_complete_);
+ return true;
+ }
+ return false;
+}
+
+void AutomationProxy::SignalInitialLoads() {
+ ::SetEvent(initial_loads_complete_);
+}
+
+void AutomationProxy::SignalNewTabUITab(int load_time) {
+ new_tab_ui_load_time_ = load_time;
+ ::SetEvent(new_tab_ui_load_complete_);
+}
+
+bool AutomationProxy::GetBrowserWindowCount(int* num_windows) {
+ if (!num_windows) {
+ NOTREACHED();
+ return false;
+ }
+
+ IPC::Message* response = NULL;
+ bool is_timeout = true;
+ bool succeeded = SendAndWaitForResponseWithTimeout(
+ new AutomationMsg_BrowserWindowCountRequest(0), &response,
+ AutomationMsg_BrowserWindowCountResponse::ID,
+ kMaxCommandExecutionTime, &is_timeout);
+ if (!succeeded)
+ return false;
+
+ if (is_timeout) {
+ DLOG(ERROR) << "GetWindowCount did not complete in a timely fashion";
+ return false;
+ }
+
+ void* iter = NULL;
+ if (!response->ReadInt(&iter, num_windows)) {
+ succeeded = false;
+ }
+
+ delete response;
+ return succeeded;
+}
+
+bool AutomationProxy::WaitForWindowCountToChange(int count, int* new_count,
+ int wait_timeout) {
+ const TimeTicks start = TimeTicks::Now();
+ const TimeDelta timeout = TimeDelta::FromMilliseconds(wait_timeout);
+ while (TimeTicks::Now() - start < timeout) {
+ bool succeeded = GetBrowserWindowCount(new_count);
+ if (!succeeded) return false;
+ if (count != *new_count) return true;
+ Sleep(automation::kSleepTime);
+ }
+ // Window count never changed.
+ return false;
+}
+
+bool AutomationProxy::WaitForWindowCountToBecome(int count,
+ int wait_timeout) {
+ const TimeTicks start = TimeTicks::Now();
+ const TimeDelta timeout = TimeDelta::FromMilliseconds(wait_timeout);
+ while (TimeTicks::Now() - start < timeout) {
+ int new_count;
+ bool succeeded = GetBrowserWindowCount(&new_count);
+ if (!succeeded) {
+ // Try again next round, but log it.
+ DLOG(ERROR) << "GetBrowserWindowCount returned false";
+ } else if (count == new_count) {
+ return true;
+ }
+ Sleep(automation::kSleepTime);
+ }
+ // Window count never reached the value we sought.
+ return false;
+}
+
+bool AutomationProxy::SetFilteredInet(bool enabled) {
+ return Send(new AutomationMsg_SetFilteredInet(0, enabled));
+}
+
+void AutomationProxy::OnMessageReceived(const IPC::Message& msg) {
+ // This won't get called unless AutomationProxy is run from
+ // inside a message loop.
+ NOTREACHED();
+}
+
+void AutomationProxy::OnChannelError() {
+ DLOG(ERROR) << "Channel error in AutomationProxy.";
+}
+
+WindowProxy* AutomationProxy::GetActiveWindow() {
+ IPC::Message* response = NULL;
+ bool is_timeout = true;
+ bool succeeded = SendAndWaitForResponseWithTimeout(
+ new AutomationMsg_ActiveWindowRequest(0), &response,
+ AutomationMsg_ActiveWindowResponse::ID,
+ kMaxCommandExecutionTime, &is_timeout);
+ if (!succeeded)
+ return NULL;
+
+ scoped_ptr<IPC::Message> response_deleter(response); // Delete on exit.
+ if (is_timeout) {
+ DLOG(ERROR) << "GetActiveWindow did not complete in a timely fashion";
+ return NULL;
+ }
+
+ void* iter = NULL;
+ int handle;
+ if (response->ReadInt(&iter, &handle) && (handle != 0))
+ return new WindowProxy(this, tracker_.get(), handle);
+
+ return NULL;
+}
+
+
+BrowserProxy* AutomationProxy::GetBrowserWindow(int window_index) {
+ IPC::Message* response;
+ bool is_timeout = true;
+ bool succeeded = SendAndWaitForResponseWithTimeout(
+ new AutomationMsg_BrowserWindowRequest(0, window_index), &response,
+ AutomationMsg_BrowserWindowResponse::ID,
+ kMaxCommandExecutionTime, &is_timeout);
+ if (!succeeded)
+ return NULL;
+
+ scoped_ptr<IPC::Message> response_deleter(response); // Delete on exit.
+ if (is_timeout) {
+ DLOG(ERROR) << "GetBrowserWindow did not complete in a timely fashion";
+ return NULL;
+ }
+
+ void* iter = NULL;
+ int handle;
+ if (!response->ReadInt(&iter, &handle) || (handle == 0)) {
+ DLOG(ERROR) << "Bad response from the window getter.";
+ return NULL;
+ }
+ return new BrowserProxy(this, tracker_.get(), handle);
+}
+
+BrowserProxy* AutomationProxy::GetLastActiveBrowserWindow() {
+ IPC::Message* response;
+ bool is_timeout = true;
+ bool succeeded = SendAndWaitForResponseWithTimeout(
+ new AutomationMsg_LastActiveBrowserWindowRequest(0),
+ &response, AutomationMsg_LastActiveBrowserWindowResponse::ID,
+ kMaxCommandExecutionTime, &is_timeout);
+ if (!succeeded)
+ return NULL;
+
+ scoped_ptr<IPC::Message> response_deleter(response); // Delete on exit.
+ if (is_timeout) {
+ DLOG(ERROR) << "GetLastActiveBrowserWindow did not complete in a timely fashion";
+ return NULL;
+ }
+
+ void* iter = NULL;
+ int handle;
+ if (!response->ReadInt(&iter, &handle) || (handle == 0)) {
+ DLOG(ERROR) << "Bad response from the window getter.";
+ return NULL;
+ }
+ return new BrowserProxy(this, tracker_.get(), handle);
+}
+
+BrowserProxy* AutomationProxy::GetBrowserForWindow(WindowProxy* window) {
+ return GetBrowserForWindowWithTimeout(window, INFINITE, NULL);
+}
+
+BrowserProxy* AutomationProxy::GetBrowserForWindowWithTimeout(
+ WindowProxy* window, uint32 timeout_ms, bool* is_timeout) {
+ DCHECK(window);
+ if (!window->is_valid() || !window->handle())
+ return false;
+
+ IPC::Message* response = NULL;
+ bool succeeded = SendAndWaitForResponseWithTimeout(
+ new AutomationMsg_BrowserForWindowRequest(0, window->handle()), &response,
+ AutomationMsg_BrowserForWindowResponse::ID, timeout_ms, is_timeout);
+ if (!succeeded)
+ return NULL;
+
+ scoped_ptr<IPC::Message> response_deleter(response); // Delete on exit.
+ int browser_handle = 0;
+ void* iter = NULL;
+ bool handle_ok;
+ succeeded = response->ReadBool(&iter, &handle_ok);
+ if (succeeded)
+ succeeded = response->ReadInt(&iter, &browser_handle);
+
+ if (succeeded) {
+ return new BrowserProxy(this, tracker_.get(), browser_handle);
+ } else {
+ return NULL;
+ }
+}
+
+WindowProxy* AutomationProxy::GetWindowForBrowser(BrowserProxy* browser) {
+ if (!browser->is_valid() || !browser->handle())
+ return false;
+
+ IPC::Message* response = NULL;
+ bool succeeded = SendAndWaitForResponse(
+ new AutomationMsg_WindowForBrowserRequest(0, browser->handle()), &response,
+ AutomationMsg_WindowForBrowserResponse::ID);
+ if (!succeeded)
+ return NULL;
+
+ scoped_ptr<IPC::Message> response_deleter(response); // Delete on exit.
+ int window_handle;
+ void* iter = NULL;
+ bool handle_ok;
+ succeeded = response->ReadBool(&iter, &handle_ok);
+ if (succeeded)
+ succeeded = response->ReadInt(&iter, &window_handle);
+
+ if (succeeded) {
+ return new WindowProxy(this, tracker_.get(), window_handle);
+ } else {
+ return NULL;
+ }
+}
+
+AutocompleteEditProxy* AutomationProxy::GetAutocompleteEditForBrowser(
+ BrowserProxy* browser) {
+ if (!browser->is_valid() || !browser->handle())
+ return NULL;
+
+ IPC::Message* response = NULL;
+ if (!SendAndWaitForResponse(
+ new AutomationMsg_AutocompleteEditForBrowserRequest(0, browser->handle()),
+ &response, AutomationMsg_AutocompleteEditForBrowserResponse::ID))
+ return NULL;
+ scoped_ptr<IPC::Message> response_deleter(response);
+
+ int autocomplete_edit_handle;
+ void* iter = NULL;
+ bool handle_ok;
+ if (!response->ReadBool(&iter, &handle_ok) ||
+ !response->ReadInt(&iter, &autocomplete_edit_handle))
+ return NULL;
+
+ return new AutocompleteEditProxy(this, tracker_.get(),
+ autocomplete_edit_handle);
+}
+
+bool AutomationProxy::SendAndWaitForResponse(IPC::Message* request,
+ IPC::Message** response,
+ int response_type) {
+ return SendAndWaitForResponseWithTimeout(request, response, response_type,
+ INFINITE, NULL);
+}
+
+bool AutomationProxy::SendAndWaitForResponseWithTimeout(
+ IPC::Message* request,
+ IPC::Message** response,
+ int response_type,
+ uint32 timeout_ms,
+ bool* is_timeout) {
+
+ DCHECK(request);
+ DCHECK(response);
+ DCHECK(!current_request_) <<
+ "Only one synchronous request should exist at any given time.";
+
+ scoped_refptr<AutomationRequest> req = new AutomationRequest;
+ current_request_ = req;
+
+ // Rewrite the message's routing ID so that we'll recognize the response
+ // to it when it comes back.
+ request->set_routing_id(req->routing_id());
+ bool result = Send(request) && req->WaitForResponse(timeout_ms, is_timeout);
+ if (!result || req->response().type() != response_type) {
+ // If Send() or WaitForResponse() failed, current_request_ may not have
+ // gotten cleared by the background thread, so we'll clear it here.
+ current_request_ = NULL;
+ return false;
+ }
+ req->GrabResponse(response);
+
+ return true;
+}
+
+void AutomationProxy::InvalidateHandle(const IPC::Message& message) {
+ void* iter = NULL;
+ int handle;
+
+ if (message.ReadInt(&iter, &handle)) {
+ tracker_->InvalidateHandle(handle);
+ }
+}
+
+bool AutomationProxy::OpenNewBrowserWindow(int show_command) {
+ return Send(new AutomationMsg_OpenNewBrowserWindow(0, show_command));
+}
+
+TabProxy* AutomationProxy::CreateExternalTab(HWND* external_tab_container) {
+ IPC::Message* response = NULL;
+ bool succeeded = SendAndWaitForResponse(
+ new AutomationMsg_CreateExternalTab(0), &response,
+ AutomationMsg_CreateExternalTabResponse::ID);
+ if (!succeeded) {
+ return NULL;
+ }
+ void* iter = NULL;
+ int handle = 0;
+ TabProxy* tab_proxy = NULL;
+ if (IPC::ReadParam(response, &iter, external_tab_container) &&
+ IsWindow(*external_tab_container)) {
+ if (response->ReadInt(&iter, &handle) &&
+ (handle >= 0)) {
+ succeeded = true;
+ tab_proxy = new TabProxy(this, tracker_.get(), handle);
+ }
+ } else {
+ succeeded = false;
+ }
+ delete response;
+ return tab_proxy;
+}
diff --git a/chrome/test/automation/automation_proxy.h b/chrome/test/automation/automation_proxy.h
new file mode 100644
index 0000000..e8d63b5
--- /dev/null
+++ b/chrome/test/automation/automation_proxy.h
@@ -0,0 +1,240 @@
+// 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.
+
+#ifndef CHROME_TEST_AUTOMATION_AUTOMATION_PROXY_H__
+#define CHROME_TEST_AUTOMATION_AUTOMATION_PROXY_H__
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/scoped_ptr.h"
+#include "base/thread.h"
+#include "chrome/common/ipc_channel_proxy.h"
+#include "chrome/common/ipc_message.h"
+#include "chrome/test/automation/automation_handle_tracker.h"
+#include "chrome/test/automation/automation_messages.h"
+
+class AutomationRequest;
+class BrowserProxy;
+class WindowProxy;
+class TabProxy;
+class AutocompleteEditProxy;
+
+// This is an interface that AutomationProxy-related objects can use to
+// access the message-sending abilities of the Proxy.
+class AutomationMessageSender : public IPC::Message::Sender {
+ public:
+ // Sends a message synchronously (from the perspective of the caller's
+ // thread, at least); it doesn't return until a response has been received.
+ // This method takes ownership of the request object passed in. The caller
+ // is responsible for deleting the response object when they're done with it.
+ // response_type should be set to the message type of the expected response.
+ // A response object will only be available if the method returns true.
+ // NOTE: This method will overwrite any routing_id on the request message,
+ // since it uses this field to match the response up with the request.
+ virtual bool SendAndWaitForResponse(IPC::Message* request,
+ IPC::Message** response,
+ int response_type) = 0;
+
+ // Sends a message synchronously; it doesn't return until a response has been
+ // received or a timeout has expired.
+ // The function returns true if a response is received, and returns false if
+ // there is a failure or timeout (in milliseconds). If return after timeout,
+ // is_timeout is set to true.
+ // See the comments in SendAndWaitForResponse for other details on usage.
+ // NOTE: When timeout occurs, the connection between proxy provider may be
+ // in transit state. Specifically, there might be pending IPC messages,
+ // and the proxy provider might be still working on the previous
+ // request.
+ virtual bool SendAndWaitForResponseWithTimeout(IPC::Message* request,
+ IPC::Message** response,
+ int response_type,
+ uint32 timeout_ms,
+ bool* is_timeout) = 0;
+};
+
+// This is the interface that external processes can use to interact with
+// a running instance of the app.
+class AutomationProxy : public IPC::Channel::Listener,
+ public AutomationMessageSender {
+ public:
+ AutomationProxy();
+ virtual ~AutomationProxy();
+
+ // IPC callback
+ virtual void OnMessageReceived(const IPC::Message& msg);
+ virtual void OnChannelError();
+
+ // Waits for the app to launch and the automation provider to say hello
+ // (the app isn't fully done loading by this point).
+ // Returns true if the launch is successful
+ bool WaitForAppLaunch();
+
+ // Waits for any initial page loads to complete.
+ // NOTE: this only fires once for a run of the application.
+ // Returns true if the load is successful
+ bool WaitForInitialLoads();
+
+ // Waits for the initial destinations tab to report that it has finished
+ // querying. |load_time| is filled in with how long it took, in milliseconds.
+ // NOTE: this only fires once for a run of the application.
+ // Returns true if the load is successful.
+ bool WaitForInitialNewTabUILoad(int* load_time);
+
+ // Open a new browser window, returning true on success. |show_command|
+ // identifies how the window should be shown.
+ // False likely indicates an IPC error.
+ bool OpenNewBrowserWindow(int show_command);
+
+ // Fills the number of open browser windows into the given variable, returning
+ // true on success. False likely indicates an IPC error.
+ bool GetBrowserWindowCount(int* num_windows);
+
+ // Block the thread until the window count changes.
+ // First parameter is the original window count.
+ // The second parameter is updated with the number of window tabs.
+ // The third parameter specifies the timeout length for the wait loop.
+ // Returns false if the window count does not change before time out.
+ // TODO(evanm): this function has a confusing name and semantics; it should
+ // be deprecated for WaitForWindowCountToBecome.
+ bool WaitForWindowCountToChange(int count, int* new_counter,
+ int wait_timeout);
+
+ // Block the thread until the window count becomes the provided value.
+ // Returns true on success.
+ bool WaitForWindowCountToBecome(int target_count, int wait_timeout);
+
+ // Returns the BrowserProxy for the browser window at the given index,
+ // transferring ownership of the pointer to the caller.
+ // On failure, returns NULL.
+ //
+ // Use GetBrowserWindowCount to see how many browser windows you can ask for.
+ // Window numbers are 0-based.
+ BrowserProxy* GetBrowserWindow(int window_index);
+
+ // Returns the BrowserProxy for the browser window which was last active,
+ // transferring ownership of the pointer to the caller.
+ // If there was no last active browser window, or the last active browser
+ // window no longer exists (for example, if it was closed), returns
+ // GetBrowserWindow(0).
+ BrowserProxy* GetLastActiveBrowserWindow();
+
+ // Returns the WindowProxy for the currently active window, transferring
+ // ownership of the pointer to the caller.
+ // On failure, returns NULL.
+ WindowProxy* GetActiveWindow();
+
+ // Returns the browser this window corresponds to, or NULL if this window
+ // is not a browser. The caller owns the returned BrowserProxy.
+ BrowserProxy* GetBrowserForWindow(WindowProxy* window);
+
+ // Same as GetBrowserForWindow except return NULL if response isn't received
+ // before the specified timeout.
+ BrowserProxy* GetBrowserForWindowWithTimeout(WindowProxy* window,
+ uint32 timeout_ms,
+ bool* is_timeout);
+
+ // Returns the WindowProxy for this browser's window. It can be used to
+ // retreive view bounds, simulate clicks and key press events. The caller
+ // owns the returned WindowProxy.
+ // On failure, returns NULL.
+ WindowProxy* GetWindowForBrowser(BrowserProxy* browser);
+
+ // Returns an AutocompleteEdit for this browser's window. It can be used to
+ // manipulate the omnibox. The caller owns the returned pointer.
+ // On failure, returns NULL.
+ AutocompleteEditProxy* GetAutocompleteEditForBrowser(BrowserProxy* browser);
+
+ // Tells the browser to enable or disable network request filtering. Returns
+ // false if the message fails to send to the browser.
+ bool SetFilteredInet(bool enabled);
+
+ // These methods are intended to be called by the background thread
+ // to signal that the given event has occurred, and that any corresponding
+ // Wait... function can return.
+ void SignalAppLaunch();
+ void SignalInitialLoads();
+ // load_time is how long, in ms, the tab contents took to load.
+ void SignalNewTabUITab(int load_time);
+
+ // Returns the ID of the automation IPC channel, so that it can be
+ // passed to the app as a launch parameter.
+ const std::wstring& channel_id() const { return channel_id_; }
+
+ // AutomationMessageSender implementations.
+ virtual bool Send(IPC::Message* message) { return channel_->Send(message); }
+ virtual bool SendAndWaitForResponse(IPC::Message* request,
+ IPC::Message** response,
+ int response_type);
+ virtual bool SendAndWaitForResponseWithTimeout(IPC::Message* request,
+ IPC::Message** response,
+ int response_type,
+ uint32 timeout_ms,
+ bool* is_timeout);
+
+ // Returns the current AutomationRequest object.
+ AutomationRequest* current_request() { return current_request_; }
+ // Clears the current AutomationRequest object.
+ void clear_current_request() { current_request_ = NULL; }
+
+ // Wrapper over AutomationHandleTracker::InvalidateHandle. Receives the message
+ // from AutomationProxy, unpacks the messages and routes that call to the
+ // tracker.
+ void InvalidateHandle(const IPC::Message& message);
+
+ // Creates a tab that can hosted in an external process. The function
+ // returns a TabProxy representing the tab as well as a window handle
+ // that can be reparented in another process.
+ TabProxy* AutomationProxy::CreateExternalTab(HWND* external_tab_container);
+ private:
+ DISALLOW_EVIL_CONSTRUCTORS(AutomationProxy);
+
+ void InitializeEvents();
+ void InitializeChannelID();
+ void InitializeThread();
+ void InitializeChannel();
+ void InitializeHandleTracker();
+
+ std::wstring channel_id_;
+ scoped_ptr<Thread> thread_;
+ scoped_ptr<IPC::ChannelProxy> channel_;
+ scoped_ptr<AutomationHandleTracker> tracker_;
+
+ HANDLE app_launched_;
+ HANDLE initial_loads_complete_;
+ HANDLE new_tab_ui_load_complete_;
+ int new_tab_ui_load_time_;
+
+ AutomationRequest* current_request_;
+
+ static const int kMaxCommandExecutionTime; // Delay to let the browser
+ // execute the command.;
+};
+
+#endif // CHROME_TEST_AUTOMATION_AUTOMATION_PROXY_H__
diff --git a/chrome/test/automation/automation_proxy_uitest.cc b/chrome/test/automation/automation_proxy_uitest.cc
new file mode 100644
index 0000000..b639007
--- /dev/null
+++ b/chrome/test/automation/automation_proxy_uitest.cc
@@ -0,0 +1,831 @@
+// 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.
+
+#include <string>
+
+#include "base/file_util.h"
+#include "base/string_util.h"
+#include "chrome/app/chrome_dll_resource.h"
+#include "chrome/browser/view_ids.h"
+#include "chrome/common/chrome_constants.h"
+#include "chrome/common/json_value_serializer.h"
+#include "chrome/test/automation/constrained_window_proxy.h"
+#include "chrome/test/automation/browser_proxy.h"
+#include "chrome/test/automation/tab_proxy.h"
+#include "chrome/test/automation/window_proxy.h"
+#include "chrome/test/ui/ui_test.h"
+#include "chrome/views/event.h"
+#include "net/base/net_util.h"
+
+typedef UITest AutomationProxyTest;
+
+class AutomationProxyVisibleTest : public UITest {
+ protected:
+ AutomationProxyVisibleTest() {
+ show_window_ = true;
+ }
+};
+
+TEST_F(AutomationProxyTest, GetBrowserWindowCount) {
+ int window_count = 0;
+ EXPECT_TRUE(automation()->GetBrowserWindowCount(&window_count));
+ EXPECT_EQ(1, window_count);
+#ifdef NDEBUG
+ ASSERT_FALSE(automation()->GetBrowserWindowCount(NULL));
+#endif
+}
+
+TEST_F(AutomationProxyTest, GetBrowserWindow) {
+ {
+ scoped_ptr<BrowserProxy> window(automation()->GetBrowserWindow(0));
+ ASSERT_TRUE(window.get());
+ }
+
+ {
+ scoped_ptr<BrowserProxy> window(automation()->GetBrowserWindow(-1));
+ ASSERT_FALSE(window.get());
+ }
+
+ {
+ scoped_ptr<BrowserProxy> window(automation()->GetBrowserWindow(1));
+ ASSERT_FALSE(window.get());
+ }
+};
+
+TEST_F(AutomationProxyVisibleTest, WindowGetViewBounds) {
+ {
+ scoped_ptr<BrowserProxy> browser(automation()->GetBrowserWindow(0));
+ ASSERT_TRUE(browser.get());
+ scoped_ptr<WindowProxy> window(
+ automation()->GetWindowForBrowser(browser.get()));
+ ASSERT_TRUE(window.get());
+
+ scoped_ptr<TabProxy> tab1(browser->GetTab(0));
+ ASSERT_TRUE(tab1.get());
+ GURL tab1_url;
+ ASSERT_TRUE(tab1->GetCurrentURL(&tab1_url));
+
+ // Add another tab so we can simulate dragging.
+ ASSERT_TRUE(browser->AppendTab(GURL("about:")));
+
+ scoped_ptr<TabProxy> tab2(browser->GetTab(1));
+ ASSERT_TRUE(tab2.get());
+ GURL tab2_url;
+ ASSERT_TRUE(tab2->GetCurrentURL(&tab2_url));
+
+ EXPECT_NE(tab1_url.spec(), tab2_url.spec());
+
+ gfx::Rect bounds;
+ ASSERT_TRUE(window->GetViewBounds(VIEW_ID_TAB_0, &bounds, false));
+ EXPECT_GT(bounds.x(), 0);
+ EXPECT_GT(bounds.width(), 0);
+ EXPECT_GT(bounds.height(), 0);
+
+ gfx::Rect bounds2;
+ ASSERT_TRUE(window->GetViewBounds(VIEW_ID_TAB_LAST, &bounds2, false));
+ EXPECT_GT(bounds2.width(), 0);
+ EXPECT_GT(bounds2.height(), 0);
+ EXPECT_GT(bounds2.x(), bounds.x());
+ EXPECT_EQ(bounds2.y(), bounds.y());
+
+ gfx::Rect urlbar_bounds;
+ ASSERT_TRUE(window->GetViewBounds(VIEW_ID_LOCATION_BAR, &urlbar_bounds,
+ false));
+ EXPECT_GT(urlbar_bounds.x(), 0);
+ EXPECT_GT(urlbar_bounds.y(), 0);
+ EXPECT_GT(urlbar_bounds.width(), 0);
+ EXPECT_GT(urlbar_bounds.height(), 0);
+
+ /*
+
+ TODO(beng): uncomment this section or move to interactive_ui_tests post
+ haste!
+
+ // Now that we know where the tabs are, let's try dragging one.
+ POINT start;
+ POINT end;
+ start.x = bounds.x() + bounds.width() / 2;
+ start.y = bounds.y() + bounds.height() / 2;
+ end.x = start.x + 2 * bounds.width() / 3;
+ end.y = start.y;
+ ASSERT_TRUE(browser->SimulateDrag(start, end,
+ ChromeViews::Event::EF_LEFT_BUTTON_DOWN));
+
+ // Check to see that the drag event successfully swapped the two tabs.
+ tab1.reset(browser->GetTab(0));
+ ASSERT_TRUE(tab1.get());
+ GURL tab1_new_url;
+ ASSERT_TRUE(tab1->GetCurrentURL(&tab1_new_url));
+
+ tab2.reset(browser->GetTab(1));
+ ASSERT_TRUE(tab2.get());
+ GURL tab2_new_url;
+ ASSERT_TRUE(tab2->GetCurrentURL(&tab2_new_url));
+
+ EXPECT_EQ(tab1_url.spec(), tab2_new_url.spec());
+ EXPECT_EQ(tab2_url.spec(), tab1_new_url.spec());
+
+ */
+ }
+}
+
+TEST_F(AutomationProxyTest, GetTabCount) {
+ scoped_ptr<BrowserProxy> window(automation()->GetBrowserWindow(0));
+ ASSERT_TRUE(window.get());
+
+ int tab_count = 0;
+ ASSERT_TRUE(window->GetTabCount(&tab_count));
+ ASSERT_EQ(1, tab_count);
+}
+
+TEST_F(AutomationProxyTest, GetActiveTabIndex) {
+ scoped_ptr<BrowserProxy> window(automation()->GetBrowserWindow(0));
+ ASSERT_TRUE(window.get());
+
+ int active_tab_index = -1;
+ ASSERT_TRUE(window->GetActiveTabIndex(&active_tab_index));
+ ASSERT_EQ(0, active_tab_index);
+}
+
+TEST_F(AutomationProxyVisibleTest, AppendTab) {
+ scoped_ptr<BrowserProxy> window(automation()->GetBrowserWindow(0));
+ ASSERT_TRUE(window.get());
+
+ int original_tab_count;
+ ASSERT_TRUE(window->GetTabCount(&original_tab_count));
+ ASSERT_EQ(1, original_tab_count); // By default there are 2 tabs opened.
+
+ int original_active_tab_index;
+ ASSERT_TRUE(window->GetActiveTabIndex(&original_active_tab_index));
+ ASSERT_EQ(0, original_active_tab_index); // By default 0-th tab is active
+
+ ASSERT_TRUE(window->AppendTab(GURL("about:blank")));
+ int tab_count;
+ ASSERT_TRUE(window->GetTabCount(&tab_count));
+ ASSERT_EQ(original_tab_count + 1, tab_count);
+
+ int active_tab_index = -1;
+ ASSERT_TRUE(window->GetActiveTabIndex(&active_tab_index));
+ ASSERT_EQ(tab_count - 1, active_tab_index);
+ ASSERT_NE(original_active_tab_index, active_tab_index);
+
+ std::wstring filename(test_data_directory_);
+ file_util::AppendToPath(&filename, L"title2.html");
+ ASSERT_TRUE(window->AppendTab(net_util::FilePathToFileURL(filename)));
+
+ int appended_tab_index;
+ // Append tab will also be active tab
+ ASSERT_TRUE(window->GetActiveTabIndex(&appended_tab_index));
+
+ scoped_ptr<TabProxy> tab(window->GetTab(appended_tab_index));
+ ASSERT_TRUE(tab.get());
+ std::wstring title;
+ ASSERT_TRUE(tab->GetTabTitle(&title));
+ ASSERT_STREQ(L"Title Of Awesomeness", title.c_str());
+}
+
+TEST_F(AutomationProxyTest, ActivateTab) {
+ scoped_ptr<BrowserProxy> window(automation()->GetBrowserWindow(0));
+ ASSERT_TRUE(window.get());
+
+ ASSERT_TRUE(window->AppendTab(GURL("about:blank")));
+
+ int at_index = 1;
+ ASSERT_TRUE(window->ActivateTab(at_index));
+ int active_tab_index = -1;
+ ASSERT_TRUE(window->GetActiveTabIndex(&active_tab_index));
+ ASSERT_EQ(at_index, active_tab_index);
+
+ at_index = 0;
+ ASSERT_TRUE(window->ActivateTab(at_index));
+ ASSERT_TRUE(window->GetActiveTabIndex(&active_tab_index));
+ ASSERT_EQ(at_index, active_tab_index);
+}
+
+
+TEST_F(AutomationProxyTest, GetTab) {
+ scoped_ptr<BrowserProxy> window(automation()->GetBrowserWindow(0));
+ ASSERT_TRUE(window.get());
+ {
+ scoped_ptr<TabProxy> tab(window->GetTab(0));
+ ASSERT_TRUE(tab.get());
+ std::wstring title;
+ ASSERT_TRUE(tab->GetTabTitle(&title));
+ // BUG [634097] : expected title should be "about:blank"
+ ASSERT_STREQ(L"", title.c_str());
+ }
+
+ {
+ ASSERT_FALSE(window->GetTab(-1));
+ }
+
+ {
+ scoped_ptr<TabProxy> tab;
+ tab.reset(window->GetTab(1));
+ ASSERT_FALSE(tab.get());
+ }
+};
+
+TEST_F(AutomationProxyTest, NavigateToURL) {
+ scoped_ptr<BrowserProxy> window(automation()->GetBrowserWindow(0));
+ ASSERT_TRUE(window.get());
+ scoped_ptr<TabProxy> tab(window->GetTab(0));
+ ASSERT_TRUE(tab.get());
+
+ std::wstring title;
+ ASSERT_TRUE(tab->GetTabTitle(&title));
+ // BUG [634097] : expected title should be "about:blank"
+ ASSERT_STREQ(L"", title.c_str());
+
+ std::wstring filename(test_data_directory_);
+ file_util::AppendToPath(&filename, L"title2.html");
+
+ tab->NavigateToURL(net_util::FilePathToFileURL(filename));
+ ASSERT_TRUE(tab->GetTabTitle(&title));
+ ASSERT_STREQ(L"Title Of Awesomeness", title.c_str());
+
+ // TODO(vibhor) : Add a test using testserver.
+}
+
+// This test is disabled. See bug 794412
+TEST_F(AutomationProxyTest, DISABLED_NavigateToURLWithTimeout1) {
+ scoped_ptr<BrowserProxy> window(automation()->GetBrowserWindow(0));
+ ASSERT_TRUE(window.get());
+ scoped_ptr<TabProxy> tab(window->GetTab(0));
+ ASSERT_TRUE(tab.get());
+
+ std::wstring filename(test_data_directory_);
+ file_util::AppendToPath(&filename, L"title2.html");
+
+ bool is_timeout;
+ tab->NavigateToURLWithTimeout(net_util::FilePathToFileURL(filename),
+ 10000, &is_timeout);
+ ASSERT_FALSE(is_timeout);
+
+ std::wstring title;
+ ASSERT_TRUE(tab->GetTabTitle(&title));
+ ASSERT_STREQ(L"Title Of Awesomeness", title.c_str());
+
+ tab->NavigateToURLWithTimeout(net_util::FilePathToFileURL(filename),
+ 1, &is_timeout);
+ ASSERT_TRUE(is_timeout);
+
+ Sleep(10);
+}
+
+// This test is disabled. See bug 794412.
+TEST_F(AutomationProxyTest, DISABLED_NavigateToURLWithTimeout2) {
+ scoped_ptr<BrowserProxy> window(automation()->GetBrowserWindow(0));
+ ASSERT_TRUE(window.get());
+ scoped_ptr<TabProxy> tab(window->GetTab(0));
+ tab.reset(window->GetTab(0));
+ ASSERT_TRUE(tab.get());
+
+ std::wstring filename1(test_data_directory_);
+ file_util::AppendToPath(&filename1, L"title1.html");
+
+ bool is_timeout;
+ tab->NavigateToURLWithTimeout(net_util::FilePathToFileURL(filename1),
+ 1, &is_timeout);
+ ASSERT_TRUE(is_timeout);
+
+ std::wstring filename2(test_data_directory_);
+ file_util::AppendToPath(&filename2, L"title2.html");
+ tab->NavigateToURLWithTimeout(net_util::FilePathToFileURL(filename2),
+ 10000, &is_timeout);
+ ASSERT_FALSE(is_timeout);
+
+ Sleep(10);
+}
+
+TEST_F(AutomationProxyTest, GoBackForward) {
+ scoped_ptr<BrowserProxy> window(automation()->GetBrowserWindow(0));
+ ASSERT_TRUE(window.get());
+ scoped_ptr<TabProxy> tab(window->GetTab(0));
+ ASSERT_TRUE(tab.get());
+
+ std::wstring title;
+ ASSERT_TRUE(tab->GetTabTitle(&title));
+ // BUG [634097] : expected title should be "about:blank"
+ ASSERT_STREQ(L"", title.c_str());
+
+ ASSERT_FALSE(tab->GoBack());
+ ASSERT_TRUE(tab->GetTabTitle(&title));
+ ASSERT_STREQ(L"", title.c_str());
+
+ std::wstring filename(test_data_directory_);
+ file_util::AppendToPath(&filename, L"title2.html");
+ ASSERT_TRUE(tab->NavigateToURL(net_util::FilePathToFileURL(filename)));
+ ASSERT_TRUE(tab->GetTabTitle(&title));
+ ASSERT_STREQ(L"Title Of Awesomeness", title.c_str());
+
+ ASSERT_TRUE(tab->GoBack());
+ ASSERT_TRUE(tab->GetTabTitle(&title));
+ // BUG [634097] : expected title should be "about:blank"
+ ASSERT_STREQ(L"", title.c_str());
+
+ ASSERT_TRUE(tab->GoForward());
+ ASSERT_TRUE(tab->GetTabTitle(&title));
+ ASSERT_STREQ(L"Title Of Awesomeness", title.c_str());
+
+ ASSERT_FALSE(tab->GoForward());
+ ASSERT_TRUE(tab->GetTabTitle(&title));
+ ASSERT_STREQ(L"Title Of Awesomeness", title.c_str());
+}
+
+TEST_F(AutomationProxyTest, GetCurrentURL) {
+ scoped_ptr<BrowserProxy> window(automation()->GetBrowserWindow(0));
+ ASSERT_TRUE(window.get());
+ scoped_ptr<TabProxy> tab(window->GetTab(0));
+ ASSERT_TRUE(tab.get());
+ GURL url;
+ ASSERT_TRUE(tab->GetCurrentURL(&url));
+ ASSERT_STREQ("about:blank", url.spec().c_str());
+
+ std::wstring filename(test_data_directory_);
+ file_util::AppendToPath(&filename, L"cookie1.html");
+ GURL newurl = net_util::FilePathToFileURL(filename);
+ ASSERT_TRUE(tab->NavigateToURL(newurl));
+ ASSERT_TRUE(tab->GetCurrentURL(&url));
+ // compare canonical urls...
+ ASSERT_STREQ(newurl.spec().c_str(), url.spec().c_str());
+}
+
+class AutomationProxyTest2 : public AutomationProxyVisibleTest {
+ protected:
+ AutomationProxyTest2() {
+ document1_ = test_data_directory_;
+ file_util::AppendToPath(&document1_, L"title1.html");
+
+ document2_ = test_data_directory_;
+ file_util::AppendToPath(&document2_, L"title2.html");
+ launch_arguments_ = document1_ + L" " + document2_;
+ }
+
+ std::wstring document1_;
+ std::wstring document2_;
+};
+
+TEST_F(AutomationProxyTest2, GetActiveTabIndex) {
+ scoped_ptr<BrowserProxy> window(automation()->GetBrowserWindow(0));
+ ASSERT_TRUE(window.get());
+
+ int active_tab_index = -1;
+ ASSERT_TRUE(window->GetActiveTabIndex(&active_tab_index));
+ int tab_count;
+ ASSERT_TRUE(window->GetTabCount(&tab_count));
+ ASSERT_EQ(0, active_tab_index);
+ int at_index = 1;
+ ASSERT_TRUE(window->ActivateTab(at_index));
+ ASSERT_TRUE(window->GetActiveTabIndex(&active_tab_index));
+ ASSERT_EQ(at_index, active_tab_index);
+}
+
+TEST_F(AutomationProxyTest2, GetTabTitle) {
+ scoped_ptr<BrowserProxy> window(automation()->GetBrowserWindow(0));
+ ASSERT_TRUE(window.get());
+ scoped_ptr<TabProxy> tab(window->GetTab(0));
+ ASSERT_TRUE(tab.get());
+ std::wstring title;
+ ASSERT_TRUE(tab->GetTabTitle(&title));
+ ASSERT_STREQ(L"title1.html", title.c_str());
+
+ tab.reset(window->GetTab(1));
+ ASSERT_TRUE(tab.get());
+ ASSERT_TRUE(tab->GetTabTitle(&title));
+ ASSERT_STREQ(L"Title Of Awesomeness", title.c_str());
+}
+
+TEST_F(AutomationProxyTest, Cookies) {
+ GURL url(L"http://mojo.jojo.google.com");
+ std::string value_result;
+
+ scoped_ptr<BrowserProxy> window(automation()->GetBrowserWindow(0));
+ ASSERT_TRUE(window.get());
+
+ scoped_ptr<TabProxy> tab(window->GetTab(0));
+ ASSERT_TRUE(tab.get());
+
+ // test setting the cookie:
+ ASSERT_TRUE(tab->SetCookie(url, "foo=baz"));
+
+ ASSERT_TRUE(tab->GetCookieByName(url, "foo", &value_result));
+ ASSERT_FALSE(value_result.empty());
+ ASSERT_STREQ("baz", value_result.c_str());
+
+ // test clearing the cookie:
+ ASSERT_TRUE(tab->SetCookie(url, "foo="));
+
+ ASSERT_TRUE(tab->GetCookieByName(url, "foo", &value_result));
+ ASSERT_TRUE(value_result.empty());
+
+ // now, test that we can get multiple cookies:
+ ASSERT_TRUE(tab->SetCookie(url, "foo1=baz1"));
+ ASSERT_TRUE(tab->SetCookie(url, "foo2=baz2"));
+
+ ASSERT_TRUE(tab->GetCookies(url, &value_result));
+ ASSERT_FALSE(value_result.empty());
+ EXPECT_TRUE(value_result.find("foo1=baz1") != std::string::npos);
+ EXPECT_TRUE(value_result.find("foo2=baz2") != std::string::npos);
+}
+
+TEST_F(AutomationProxyTest, GetHWND) {
+ scoped_ptr<BrowserProxy> browser(automation()->GetBrowserWindow(0));
+ ASSERT_TRUE(browser.get());
+ scoped_ptr<WindowProxy> window(
+ automation()->GetWindowForBrowser(browser.get()));
+ ASSERT_TRUE(window.get());
+
+ HWND handle;
+ ASSERT_TRUE(window->GetHWND(&handle));
+ ASSERT_TRUE(handle);
+}
+
+TEST_F(AutomationProxyTest, NavigateToURLAsync) {
+ AutomationProxy* automation_object = automation();
+ scoped_ptr<BrowserProxy> window(automation_object->GetBrowserWindow(0));
+ ASSERT_TRUE(window.get());
+ scoped_ptr<TabProxy> tab(window->GetTab(0));
+ ASSERT_TRUE(tab.get());
+
+ std::wstring filename(test_data_directory_);
+ file_util::AppendToPath(&filename, L"cookie1.html");
+ GURL newurl = net_util::FilePathToFileURL(filename);
+
+ ASSERT_TRUE(tab->NavigateToURLAsync(newurl));
+ std::string value = WaitUntilCookieNonEmpty(tab.get(), newurl,
+ "foo", 250, 5*1000);
+ ASSERT_STREQ("baz", value.c_str());
+}
+
+TEST_F(AutomationProxyTest, AcceleratorNewTab) {
+ scoped_ptr<BrowserProxy> window(automation()->GetBrowserWindow(0));
+
+ int old_tab_count = -1;
+ ASSERT_TRUE(window->GetTabCount(&old_tab_count));
+
+ ASSERT_TRUE(window->ApplyAccelerator(IDC_NEWTAB));
+ int new_tab_count;
+ ASSERT_TRUE(window->WaitForTabCountToChange(old_tab_count, &new_tab_count,
+ 5000));
+ if (new_tab_count == -1)
+ FAIL();
+ ASSERT_EQ(old_tab_count + 1, new_tab_count);
+ scoped_ptr<TabProxy> tab(window->GetTab(new_tab_count - 1));
+ ASSERT_TRUE(tab.get());
+
+ std::wstring title;
+ int i;
+ for (i = 0; i < 10; ++i) {
+ Sleep(kWaitForActionMaxMsec / 10);
+ ASSERT_TRUE(tab->GetTabTitle(&title));
+ if (title == L"Destinations" || title == L"New Tab")
+ break;
+ }
+ // If we got to 10, the new tab failed to open.
+ ASSERT_NE(10, i);
+}
+
+class AutomationProxyTest4 : public UITest {
+ protected:
+ AutomationProxyTest4() : UITest() {
+ dom_automation_enabled_ = true;
+ }
+};
+
+std::wstring SynthesizeJSURL(const std::wstring& value) {
+ std::wstring jscript;
+ SStringPrintf(&jscript,
+ L"javascript:void(window.domAutomationController.send(%s));", value.c_str());
+ return jscript;
+}
+
+TEST_F(AutomationProxyTest4, StringValueIsEchoedByDomAutomationController) {
+ scoped_ptr<BrowserProxy> window(automation()->GetBrowserWindow(0));
+ ASSERT_TRUE(window.get());
+
+ scoped_ptr<TabProxy> tab(window->GetTab(0));
+ ASSERT_TRUE(tab.get());
+
+ std::wstring expected(L"string");
+ std::wstring jscript = SynthesizeJSURL(L"\"" + expected + L"\"");
+ std::wstring actual;
+ ASSERT_TRUE(tab->ExecuteAndExtractString(L"", jscript, &actual));
+ ASSERT_STREQ(expected.c_str(), actual.c_str());
+}
+
+std::wstring BooleanToString(bool bool_value) {
+ Value* value = Value::CreateBooleanValue(bool_value);
+ std::string json_string;
+ JSONStringValueSerializer serializer(&json_string);
+ serializer.Serialize(*value);
+ return UTF8ToWide(json_string);
+}
+
+TEST_F(AutomationProxyTest4, BooleanValueIsEchoedByDomAutomationController) {
+ scoped_ptr<BrowserProxy> window(automation()->GetBrowserWindow(0));
+ ASSERT_TRUE(window.get());
+
+ scoped_ptr<TabProxy> tab(window->GetTab(0));
+ ASSERT_TRUE(tab.get());
+
+ bool expected = true;
+ std::wstring jscript = SynthesizeJSURL(BooleanToString(expected));
+ bool actual = false;
+ ASSERT_TRUE(tab->ExecuteAndExtractBool(L"", jscript, &actual));
+ ASSERT_EQ(expected, actual);
+}
+
+TEST_F(AutomationProxyTest4, NumberValueIsEchoedByDomAutomationController) {
+ scoped_ptr<BrowserProxy> window(automation()->GetBrowserWindow(0));
+ ASSERT_TRUE(window.get());
+
+ scoped_ptr<TabProxy> tab(window->GetTab(0));
+ ASSERT_TRUE(tab.get());
+
+ int expected = 1;
+ int actual = 0;
+ std::wstring expected_string;
+ SStringPrintf(&expected_string, L"%d", expected);
+ std::wstring jscript = SynthesizeJSURL(expected_string);
+ ASSERT_TRUE(tab->ExecuteAndExtractInt(L"", jscript, &actual));
+ ASSERT_EQ(expected, actual);
+}
+
+// TODO(vibhor): Add a test for ExecuteAndExtractValue() for JSON Dictionary
+// type value
+
+class AutomationProxyTest3 : public UITest {
+ protected:
+ AutomationProxyTest3() : UITest() {
+ document1_ = test_data_directory_;
+ file_util::AppendToPath(&document1_, L"frame_dom_access");
+ file_util::AppendToPath(&document1_, L"frame_dom_access.html");
+
+ dom_automation_enabled_ = true;
+ launch_arguments_ = document1_;
+ }
+
+ std::wstring document1_;
+};
+
+std::wstring SynthesizeJSURLForDOMQuery(const std::wstring& id) {
+ std::wstring jscript;
+ SStringPrintf(&jscript,
+ L"javascript:void(window.domAutomationController)");
+ StringAppendF(&jscript, L".send(document.getElementById('%s').nodeName);",
+ id.c_str());
+ return jscript;
+}
+
+TEST_F(AutomationProxyTest3, FrameDocumentCanBeAccessed) {
+ scoped_ptr<BrowserProxy> window(automation()->GetBrowserWindow(0));
+ ASSERT_TRUE(window.get());
+
+ scoped_ptr<TabProxy> tab(window->GetTab(0));
+ ASSERT_TRUE(tab.get());
+
+ std::wstring actual;
+ std::wstring xpath1 = L""; // top level frame
+ std::wstring jscript1 = SynthesizeJSURLForDOMQuery(L"myinput");
+ ASSERT_TRUE(tab->ExecuteAndExtractString(xpath1, jscript1, &actual));
+ ASSERT_EQ(L"INPUT", actual);
+
+ std::wstring xpath2 = L"/html/body/iframe";
+ std::wstring jscript2 = SynthesizeJSURLForDOMQuery(L"myspan");
+ ASSERT_TRUE(tab->ExecuteAndExtractString(xpath2, jscript2, &actual));
+ ASSERT_EQ(L"SPAN", actual);
+
+ std::wstring xpath3 = L"/html/body/iframe\n/html/body/iframe";
+ std::wstring jscript3 = SynthesizeJSURLForDOMQuery(L"mydiv");
+ ASSERT_TRUE(tab->ExecuteAndExtractString(xpath3, jscript3, &actual));
+ ASSERT_EQ(L"DIV", actual);
+
+ // TODO(evanm): fix or remove this.
+ // This part of the test appears to verify that executing JS fails
+ // non-HTML pages, but the new tab is now HTML so this test isn't
+ // correct.
+#if 0
+ // Open a new Destinations tab to execute script inside.
+ window->ApplyAccelerator(IDC_NEWTAB);
+ tab.reset(window->GetTab(1));
+ ASSERT_TRUE(tab.get());
+ ASSERT_TRUE(window->ActivateTab(1));
+
+ std::wstring title;
+ int i;
+ for (i = 0; i < 10; ++i) {
+ Sleep(kWaitForActionMaxMsec / 10);
+ ASSERT_TRUE(tab->GetTabTitle(&title));
+ if (title == L"Destinations")
+ break;
+ }
+ // If we got to 10, the new tab failed to open.
+ ASSERT_NE(10, i);
+ ASSERT_FALSE(tab->ExecuteAndExtractString(xpath1, jscript1, &actual));
+#endif
+}
+
+TEST_F(AutomationProxyTest, ConstrainedWindowTest) {
+ scoped_ptr<BrowserProxy> window(automation()->GetBrowserWindow(0));
+ ASSERT_TRUE(window.get());
+
+ scoped_ptr<TabProxy> tab(window->GetTab(0));
+ tab.reset(window->GetTab(0));
+ ASSERT_TRUE(tab.get());
+
+ std::wstring filename(test_data_directory_);
+ file_util::AppendToPath(&filename, L"constrained_files");
+ file_util::AppendToPath(&filename, L"constrained_window.html");
+
+ ASSERT_TRUE(tab->NavigateToURL(net_util::FilePathToFileURL(filename)));
+
+ int count;
+ ASSERT_TRUE(tab->WaitForChildWindowCountToChange(0, &count, 5000));
+
+ ASSERT_EQ(2, count);
+
+ ConstrainedWindowProxy* cwindow = tab->GetConstrainedWindow(0);
+ ASSERT_TRUE(cwindow);
+
+ std::wstring title;
+ ASSERT_TRUE(cwindow->GetTitle(&title));
+ ASSERT_STREQ(L"Constrained Window 0 - Google Chrome", title.c_str());
+ delete cwindow;
+
+ cwindow = tab->GetConstrainedWindow(1);
+ ASSERT_TRUE(cwindow);
+ ASSERT_TRUE(cwindow->GetTitle(&title));
+ ASSERT_STREQ(L"Constrained Window 1 - Google Chrome", title.c_str());
+ delete cwindow;
+}
+
+TEST_F(AutomationProxyTest, CantEscapeByOnloadMoveto) {
+ scoped_ptr<BrowserProxy> window(automation()->GetBrowserWindow(0));
+ ASSERT_TRUE(window.get());
+
+ scoped_ptr<TabProxy> tab(window->GetTab(0));
+ tab.reset(window->GetTab(0));
+ ASSERT_TRUE(tab.get());
+
+ std::wstring filename(test_data_directory_);
+ file_util::AppendToPath(&filename, L"constrained_files");
+ file_util::AppendToPath(&filename, L"constrained_window_onload_moveto.html");
+
+ ASSERT_TRUE(tab->NavigateToURL(net_util::FilePathToFileURL(filename)));
+
+ int count;
+ ASSERT_TRUE(tab->WaitForChildWindowCountToChange(0, &count, 5000));
+
+ ASSERT_EQ(1, count);
+
+ ConstrainedWindowProxy* cwindow = tab->GetConstrainedWindow(0);
+ ASSERT_TRUE(cwindow);
+
+ gfx::Rect rect;
+ bool is_timeout = false;
+ ASSERT_TRUE(cwindow->GetBoundsWithTimeout(&rect, 1000, &is_timeout));
+ ASSERT_FALSE(is_timeout);
+ ASSERT_NE(20, rect.x());
+ ASSERT_NE(20, rect.y());
+}
+
+bool ExternalTabHandler(HWND external_tab_window) {
+ static const wchar_t class_name[] = L"External_Tab_UI_Test_Class";
+ static const wchar_t window_title[] = L"External Tab Tester";
+
+ WNDCLASSEX wnd_class = {0};
+ wnd_class.cbSize = sizeof(wnd_class);
+ wnd_class.style = CS_HREDRAW | CS_VREDRAW;
+ wnd_class.lpfnWndProc = DefWindowProc;
+ wnd_class.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
+ wnd_class.lpszClassName = class_name;
+ ATOM result = RegisterClassEx(&wnd_class);
+ if (0 == result) {
+ return false;
+ }
+
+ unsigned long style = WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN;
+ HWND external_tab_ui_parent = CreateWindow(class_name, window_title,
+ style, CW_USEDEFAULT, 0,
+ CW_USEDEFAULT, 0, NULL, NULL,
+ NULL, NULL);
+ style = GetWindowLong(external_tab_window, GWL_STYLE);
+ style |= WS_CHILD;
+ style &= ~WS_POPUP;
+ SetWindowLong(external_tab_window, GWL_STYLE, style);
+ SetParent(external_tab_window, external_tab_ui_parent);
+ RECT client_rect = {0};
+ GetClientRect(external_tab_ui_parent, &client_rect);
+ SetWindowPos(external_tab_window, NULL, 0, 0, client_rect.right,
+ client_rect.bottom, SWP_NOZORDER);
+ ShowWindow(external_tab_window, SW_SHOW);
+ ShowWindow(external_tab_ui_parent, SW_SHOW);
+
+ // Allow the renderers to connect.
+ Sleep(1000);
+ DestroyWindow(external_tab_ui_parent);
+ return true;
+}
+
+TEST_F(AutomationProxyVisibleTest, CreateExternalTab) {
+ HWND external_tab_container = NULL;
+ scoped_ptr<TabProxy> tab(automation()->CreateExternalTab(
+ &external_tab_container));
+ EXPECT_TRUE(tab != NULL);
+ EXPECT_NE(FALSE, ::IsWindow(external_tab_container));
+ if (tab != NULL) {
+ tab->NavigateInExternalTab(GURL(L"http://www.google.com"));
+ EXPECT_EQ(true, ExternalTabHandler(external_tab_container));
+ // Since the tab goes away lazily, wait a bit
+ Sleep(1000);
+ EXPECT_FALSE(tab->is_valid());
+ }
+}
+
+TEST_F(AutomationProxyTest, AutocompleteGetSetText) {
+ scoped_ptr<BrowserProxy> browser(automation()->GetBrowserWindow(0));
+ ASSERT_TRUE(browser.get());
+ scoped_ptr<AutocompleteEditProxy> edit(
+ automation()->GetAutocompleteEditForBrowser(browser.get()));
+ ASSERT_TRUE(edit.get());
+ EXPECT_TRUE(edit->is_valid());
+ const std::wstring text_to_set = L"Lollerskates";
+ std::wstring actual_text;
+ EXPECT_TRUE(edit->SetText(text_to_set));
+ EXPECT_TRUE(edit->GetText(&actual_text));
+ EXPECT_EQ(text_to_set, actual_text);
+ scoped_ptr<AutocompleteEditProxy> edit2(
+ automation()->GetAutocompleteEditForBrowser(browser.get()));
+ EXPECT_TRUE(edit2->GetText(&actual_text));
+ EXPECT_EQ(text_to_set, actual_text);
+}
+
+TEST_F(AutomationProxyTest, AutocompleteParallelProxy)
+{
+ scoped_ptr<BrowserProxy> browser1(automation()->GetBrowserWindow(0));
+ ASSERT_TRUE(browser1.get());
+ scoped_ptr<AutocompleteEditProxy> edit1(
+ automation()->GetAutocompleteEditForBrowser(browser1.get()));
+ ASSERT_TRUE(edit1.get());
+ EXPECT_TRUE(browser1->ApplyAccelerator(IDC_DUPLICATE));
+ scoped_ptr<BrowserProxy> browser2(automation()->GetBrowserWindow(1));
+ ASSERT_TRUE(browser2.get());
+ scoped_ptr<AutocompleteEditProxy> edit2(
+ automation()->GetAutocompleteEditForBrowser(browser2.get()));
+ ASSERT_TRUE(edit2.get());
+ EXPECT_TRUE(browser2->GetTab(0)->WaitForTabToBeRestored());
+ const std::wstring text_to_set1 = L"Lollerskates";
+ const std::wstring text_to_set2 = L"Roflcopter";
+ std::wstring actual_text1, actual_text2;
+ EXPECT_TRUE(edit1->SetText(text_to_set1));
+ EXPECT_TRUE(edit2->SetText(text_to_set2));
+ EXPECT_TRUE(edit1->GetText(&actual_text1));
+ EXPECT_TRUE(edit2->GetText(&actual_text2));
+ EXPECT_EQ(text_to_set1, actual_text1);
+ EXPECT_EQ(text_to_set2, actual_text2);
+}
+
+TEST_F(AutomationProxyVisibleTest, AutocompleteMatchesTest) {
+ scoped_ptr<BrowserProxy> browser(automation()->GetBrowserWindow(0));
+ ASSERT_TRUE(browser.get());
+ scoped_ptr<AutocompleteEditProxy> edit(
+ automation()->GetAutocompleteEditForBrowser(browser.get()));
+ ASSERT_TRUE(edit.get());
+ EXPECT_TRUE(browser->ApplyAccelerator(IDC_FOCUS_LOCATION));
+ EXPECT_TRUE(edit->is_valid());
+ EXPECT_TRUE(edit->SetText(L"Roflcopter"));
+ EXPECT_TRUE(edit->WaitForQuery(30000));
+ bool query_in_progress;
+ EXPECT_TRUE(edit->IsQueryInProgress(&query_in_progress));
+ EXPECT_FALSE(query_in_progress);
+ std::vector<AutocompleteMatchData> matches;
+ EXPECT_TRUE(edit->GetAutocompleteMatches(&matches));
+ EXPECT_FALSE(matches.empty());
+}
diff --git a/chrome/test/automation/browser_proxy.cc b/chrome/test/automation/browser_proxy.cc
new file mode 100644
index 0000000..81b8900
--- /dev/null
+++ b/chrome/test/automation/browser_proxy.cc
@@ -0,0 +1,348 @@
+// 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.
+
+#include "chrome/test/automation/browser_proxy.h"
+
+#include <vector>
+
+#include "base/logging.h"
+#include "base/time.h"
+#include "chrome/test/automation/automation_constants.h"
+#include "chrome/test/automation/automation_messages.h"
+#include "chrome/test/automation/automation_proxy.h"
+#include "chrome/test/automation/tab_proxy.h"
+
+bool BrowserProxy::ActivateTab(int tab_index) {
+ return ActivateTabWithTimeout(tab_index, INFINITE, NULL);
+}
+
+bool BrowserProxy::ActivateTabWithTimeout(int tab_index, uint32 timeout_ms,
+ bool* is_timeout) {
+ if (!is_valid())
+ return false;
+
+ IPC::Message* response = NULL;
+ bool succeeded = sender_->SendAndWaitForResponseWithTimeout(
+ new AutomationMsg_ActivateTabRequest(0, handle_, tab_index), &response,
+ AutomationMsg_ActivateTabResponse::ID, timeout_ms, is_timeout);
+
+ scoped_ptr<IPC::Message> response_deleter(response); // Delete on return.
+ if (!succeeded)
+ return false;
+
+ void* iter = NULL;
+ int activate_tab_response = -1;
+ if (response->ReadInt(&iter, &activate_tab_response) &&
+ (activate_tab_response >= 0)) {
+ succeeded = true;
+ } else {
+ succeeded = false;
+ }
+
+ return succeeded;
+}
+
+bool BrowserProxy::BringToFront() {
+ return BringToFrontWithTimeout(INFINITE, NULL);
+}
+
+bool BrowserProxy::BringToFrontWithTimeout(uint32 timeout_ms,
+ bool* is_timeout) {
+ if (!is_valid())
+ return false;
+
+ IPC::Message* response = NULL;
+ bool succeeded = sender_->SendAndWaitForResponseWithTimeout(
+ new AutomationMsg_BringBrowserToFront(0, handle_), &response,
+ AutomationMsg_BringBrowserToFrontResponse::ID, timeout_ms, is_timeout);
+
+ scoped_ptr<IPC::Message> response_deleter(response); // Delete on return.
+ if (!succeeded)
+ return false;
+
+ void* iter = NULL;
+ if (!response->ReadBool(&iter, &succeeded))
+ succeeded = false;
+
+ return succeeded;
+}
+
+bool BrowserProxy::IsPageMenuCommandEnabledWithTimeout(int id,
+ uint32 timeout_ms,
+ bool* is_timeout) {
+ if (!is_valid())
+ return false;
+
+ IPC::Message* response = NULL;
+ bool succeeded = sender_->SendAndWaitForResponseWithTimeout(
+ new AutomationMsg_IsPageMenuCommandEnabled(0, handle_, id), &response,
+ AutomationMsg_IsPageMenuCommandEnabledResponse::ID, timeout_ms, is_timeout);
+
+ scoped_ptr<IPC::Message> response_deleter(response); // Delete on return.
+ if (!succeeded)
+ return false;
+
+ void* iter = NULL;
+ if (!response->ReadBool(&iter, &succeeded))
+ succeeded = false;
+
+ return succeeded;
+}
+
+bool BrowserProxy::AppendTab(const GURL& tab_url) {
+ if (!is_valid())
+ return false;
+
+ IPC::Message* response = NULL;
+
+ bool succeeded = sender_->SendAndWaitForResponse(
+ new AutomationMsg_AppendTabRequest(0, handle_, tab_url), &response,
+ AutomationMsg_AppendTabResponse::ID);
+
+ scoped_ptr<IPC::Message> response_deleter(response); // Delete on return.
+ if (!succeeded)
+ return false;
+
+ void* iter = NULL;
+ int append_tab_response = -1;
+ if (response->ReadInt(&iter, &append_tab_response) &&
+ (append_tab_response >= 0)) {
+ succeeded = true;
+ } else {
+ succeeded = false;
+ }
+
+ return succeeded;
+}
+
+bool BrowserProxy::GetActiveTabIndex(int* active_tab_index) const {
+ return GetActiveTabIndexWithTimeout(active_tab_index, INFINITE, NULL);
+}
+
+bool BrowserProxy::GetActiveTabIndexWithTimeout(int* active_tab_index,
+ uint32 timeout_ms,
+ bool* is_timeout) const {
+ if (!is_valid())
+ return false;
+
+ if (!active_tab_index) {
+ NOTREACHED();
+ return false;
+ }
+
+ IPC::Message* response = NULL;
+ bool succeeded = sender_->SendAndWaitForResponseWithTimeout(
+ new AutomationMsg_ActiveTabIndexRequest(0, handle_), &response,
+ AutomationMsg_ActiveTabIndexResponse::ID, timeout_ms, is_timeout);
+
+ scoped_ptr<IPC::Message> response_deleter(response); // Delete on return.
+ if (!succeeded)
+ return false;
+
+ void* iter = NULL;
+ int active_tab_index_response = -1;
+ if (response->ReadInt(&iter, &active_tab_index_response) &&
+ (active_tab_index_response >= 0)) {
+ *active_tab_index = active_tab_index_response;
+ } else {
+ succeeded = false;
+ }
+
+ return succeeded;
+}
+
+TabProxy* BrowserProxy::GetTab(int tab_index) const {
+ if (!is_valid())
+ return NULL;
+
+ IPC::Message* response = NULL;
+ bool succeeded = sender_->SendAndWaitForResponse(
+ new AutomationMsg_TabRequest(0, handle_, tab_index), &response,
+ AutomationMsg_TabResponse::ID);
+ scoped_ptr<IPC::Message> response_deleter(response); // Delete on return.
+ if (!succeeded)
+ return NULL;
+
+ void* iter = NULL;
+ int handle;
+
+ if (!response->ReadInt(&iter, &handle) || (handle == 0))
+ return NULL;
+ return new TabProxy(sender_, tracker_, handle);
+}
+
+TabProxy* BrowserProxy::GetActiveTab() const {
+ return GetActiveTabWithTimeout(INFINITE, NULL);
+}
+
+TabProxy* BrowserProxy::GetActiveTabWithTimeout(uint32 timeout_ms,
+ bool* is_timeout) const {
+ int active_tab_index;
+ if (!GetActiveTabIndexWithTimeout(&active_tab_index, timeout_ms, is_timeout))
+ return NULL;
+ return GetTab(active_tab_index);
+}
+
+bool BrowserProxy::GetTabCount(int* num_tabs) const {
+ return GetTabCountWithTimeout(num_tabs, INFINITE, NULL);
+}
+
+bool BrowserProxy::GetTabCountWithTimeout(int* num_tabs, uint32 timeout_ms,
+ bool* is_timeout) const {
+ if (!is_valid())
+ return false;
+
+ if (!num_tabs) {
+ NOTREACHED();
+ return false;
+ }
+
+ IPC::Message* response = NULL;
+ bool succeeded = sender_->SendAndWaitForResponseWithTimeout(
+ new AutomationMsg_TabCountRequest(0, handle_), &response,
+ AutomationMsg_TabCountResponse::ID, timeout_ms, is_timeout);
+
+ scoped_ptr<IPC::Message> response_deleter(response); // Delete on return.
+ if (!succeeded)
+ return false;
+
+ void* iter = NULL;
+ int tab_count_response = -1;
+ if (response->ReadInt(&iter, &tab_count_response) &&
+ (tab_count_response >= 0)) {
+ *num_tabs = tab_count_response;
+ } else {
+ succeeded = false;
+ }
+
+ return succeeded;
+}
+
+bool BrowserProxy::ApplyAccelerator(int id) {
+ if (!is_valid())
+ return false;
+
+ return sender_->Send(
+ new AutomationMsg_ApplyAcceleratorRequest(0, handle_, id));
+}
+
+bool BrowserProxy::SimulateDrag(const POINT& start,
+ const POINT& end,
+ int flags) {
+ return SimulateDragWithTimeout(start, end, flags, INFINITE, NULL);
+}
+
+bool BrowserProxy::SimulateDragWithTimeout(const POINT& start,
+ const POINT& end,
+ int flags,
+ uint32 timeout_ms,
+ bool* is_timeout) {
+ if (!is_valid())
+ return false;
+
+ std::vector<POINT> drag_path;
+ drag_path.push_back(start);
+ drag_path.push_back(end);
+
+ IPC::Message* response = NULL;
+ bool succeeded = sender_->SendAndWaitForResponseWithTimeout(
+ new AutomationMsg_WindowDragRequest(0, handle_, drag_path, flags),
+ &response, AutomationMsg_WindowDragResponse::ID, timeout_ms, is_timeout);
+
+ scoped_ptr<IPC::Message> response_deleter(response); // Delete on return.
+ if (!succeeded)
+ return false;
+
+ void* iter = NULL;
+ if (!response->ReadBool(&iter, &succeeded))
+ succeeded = false;
+
+ return succeeded;
+}
+
+bool BrowserProxy::WaitForTabCountToChange(int count, int* new_count,
+ int wait_timeout) {
+ const TimeTicks start = TimeTicks::Now();
+ const TimeDelta timeout = TimeDelta::FromMilliseconds(wait_timeout);
+ while (TimeTicks::Now() - start < timeout) {
+ Sleep(automation::kSleepTime);
+ bool is_timeout;
+ bool succeeded = GetTabCountWithTimeout(new_count, wait_timeout,
+ &is_timeout);
+ if (!succeeded)
+ return false;
+ if (count != *new_count)
+ return true;
+ }
+ // If we get here, the tab count hasn't changed.
+ return false;
+}
+
+bool BrowserProxy::WaitForTabToBecomeActive(int tab,
+ int wait_timeout) {
+ const TimeTicks start = TimeTicks::Now();
+ const TimeDelta timeout = TimeDelta::FromMilliseconds(wait_timeout);
+ while (TimeTicks::Now() - start < timeout) {
+ Sleep(automation::kSleepTime);
+ int active_tab;
+ if (GetActiveTabIndex(&active_tab) && active_tab == tab)
+ return true;
+ }
+ // If we get here, the active tab hasn't changed.
+ return false;
+}
+
+bool BrowserProxy::GetHWND(HWND* handle) const {
+ if (!is_valid())
+ return false;
+
+ if (!handle) {
+ NOTREACHED();
+ return false;
+ }
+
+ IPC::Message* response = NULL;
+ bool succeeded = sender_->SendAndWaitForResponse(
+ new AutomationMsg_WindowHWNDRequest(0, handle_), &response,
+ AutomationMsg_WindowHWNDResponse::ID);
+
+ scoped_ptr<IPC::Message> response_deleter(response); // Delete on return.
+ if (!succeeded)
+ return false;
+
+ HWND hwnd_response;
+ if (AutomationMsg_WindowHWNDResponse::Read(response, &hwnd_response) &&
+ hwnd_response) {
+ *handle = hwnd_response;
+ } else {
+ succeeded = false;
+ }
+
+ return succeeded;
+}
diff --git a/chrome/test/automation/browser_proxy.h b/chrome/test/automation/browser_proxy.h
new file mode 100644
index 0000000..469b377
--- /dev/null
+++ b/chrome/test/automation/browser_proxy.h
@@ -0,0 +1,164 @@
+// 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.
+
+#ifndef CHROME_TEST_AUTOMATION_BROWSER_PROXY_H__
+#define CHROME_TEST_AUTOMATION_BROWSER_PROXY_H__
+
+#include <string>
+#include <windows.h>
+#include "chrome/test/automation/automation_handle_tracker.h"
+
+class GURL;
+class TabProxy;
+
+namespace gfx {
+ class Rect;
+}
+
+// This class presents the interface to actions that can be performed on
+// a given browser window. Note that this object can be invalidated at any
+// time if the corresponding browser window in the app is closed. In that case,
+// any subsequent calls will return false immediately.
+class BrowserProxy : public AutomationResourceProxy {
+ public:
+ BrowserProxy(AutomationMessageSender* sender,
+ AutomationHandleTracker* tracker,
+ int handle)
+ : AutomationResourceProxy(tracker, sender, handle) {}
+ virtual ~BrowserProxy() {}
+
+ // Activates the tab corresponding to (zero-based) tab_index. Returns true if
+ // successful.
+ bool ActivateTab(int tab_index);
+
+ // Like ActivateTab, but returns false if response is not received before
+ // the specified timeout.
+ bool ActivateTabWithTimeout(int tab_index, uint32 timeout_ms,
+ bool* is_timeout);
+
+ // Bring the browser window to the front, activating it. Returns true on
+ // success.
+ bool BringToFront();
+
+ // Like BringToFront, but returns false if action is not completed before
+ // the specified timeout.
+ bool BringToFrontWithTimeout(uint32 timeout_ms, bool* is_timeout);
+
+ // Checks to see if a navigation command is active or not. Can also
+ // return false if action is not completed before the specified
+ // timeout; is_timeout will be set in those cases.
+ bool IsPageMenuCommandEnabledWithTimeout(int id, uint32 timeout_ms,
+ bool* is_timeout);
+
+ // Append a new tab to the TabStrip. The new tab is selected.
+ // The new tab navigates to the given tab_url.
+ // Returns true if successful.
+ // TODO(mpcomplete): If the navigation results in an auth challenge, the
+ // TabProxy we attach won't know about it. See bug 666730.
+ bool AppendTab(const GURL& tab_url);
+
+ // Gets the (zero-based) index of the currently active tab. Returns true if
+ // successful.
+ bool GetActiveTabIndex(int* active_tab_index) const;
+
+ // Like GetActiveTabIndex, but returns false if active tab is not received
+ // before the specified timeout.
+ bool GetActiveTabIndexWithTimeout(int* active_tab_index, uint32 timeout_ms,
+ bool* is_timeout) const;
+
+ // Returns the number of tabs in the given window. Returns true if
+ // the call was successful.
+ bool GetTabCount(int* num_tabs) const;
+
+ // Like GetTabCount, but returns false if tab count is not received within the
+ // before timeout.
+ bool GetTabCountWithTimeout(int* num_tabs, uint32 timeout_ms,
+ bool* is_timeout) const;
+
+ // Returns the TabProxy for the tab at the given index, transferring
+ // ownership of the pointer to the caller. On failure, returns NULL.
+ //
+ // Use GetTabCount to see how many windows you can ask for. Tab numbers
+ // are 0-based.
+ TabProxy* GetTab(int tab_index) const;
+
+ // Returns the TabProxy for the currently active tab, transferring
+ // ownership of the pointer to the caller. On failure, returns NULL.
+ TabProxy* GetActiveTab() const;
+
+ // Like GetActiveTab, but returns NULL if no response is received before
+ // the specified timout.
+ TabProxy* GetActiveTabWithTimeout(uint32 timeout_ms, bool* is_timeout) const;
+
+ // Apply the accelerator with given id (IDC_BACK, IDC_NEWTAB ...)
+ // Returns true if the call was successful.
+ //
+ // The alternate way to test the accelerators is to use the Windows messaging
+ // system to send the actual keyboard events (ui_controls.h) A precondition
+ // to using this system is that the target window should have the keyboard
+ // focus. This leads to a flaky test behavior in circumstances when the
+ // desktop screen is locked or the test is being executed over a remote
+ // desktop.
+ bool ApplyAccelerator(int id);
+
+ // Performs a drag operation between the start and end points (both defined
+ // in window coordinates). |flags| specifies which buttons are pressed for
+ // the drag, as defined in chrome/views/event.h.
+ virtual bool SimulateDrag(const POINT& start, const POINT& end, int flags);
+
+ // Like SimulateDrag, but returns false if response is not received before
+ // the specified timeout.
+ virtual bool SimulateDragWithTimeout(const POINT& start, const POINT& end,
+ int flags, uint32 timeout_ms,
+ bool* is_timeout);
+
+ // Block the thread until the tab count changes.
+ // |count| is the original tab count.
+ // |new_count| is updated with the number of new tabs.
+ // |wait_timeout| is the timeout, in milliseconds, for waiting.
+ // Returns false if the tab count does not change.
+ bool WaitForTabCountToChange(int count, int* new_count, int wait_timeout);
+
+ // Block the thread until the specified tab is the active tab.
+ // |wait_timeout| is the timeout, in milliseconds, for waiting.
+ // Returns false if the tab does not become active.
+ bool WaitForTabToBecomeActive(int tab, int wait_timeout);
+
+ // Gets the outermost HWND that corresponds to the given browser.
+ // Returns true if the call was successful.
+ // Note that ideally this should go and the version of WindowProxy should be
+ // used instead. We have to keep it for start_up_tests that test against a
+ // reference build.
+ bool GetHWND(HWND* handle) const;
+
+ private:
+ DISALLOW_EVIL_CONSTRUCTORS(BrowserProxy);
+};
+
+#endif // #define CHROME_TEST_AUTOMATION_BROWSER_PROXY_H__
diff --git a/chrome/test/automation/constrained_window_proxy.cc b/chrome/test/automation/constrained_window_proxy.cc
new file mode 100644
index 0000000..03fae09
--- /dev/null
+++ b/chrome/test/automation/constrained_window_proxy.cc
@@ -0,0 +1,92 @@
+// 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.
+
+#include "constrained_window_proxy.h"
+
+#include "chrome/test/automation/automation_messages.h"
+#include "chrome/test/automation/automation_proxy.h"
+
+bool ConstrainedWindowProxy::GetTitle(std::wstring* title) const {
+ if (!is_valid())
+ return false;
+
+ if (!title) {
+ NOTREACHED();
+ return false;
+ }
+
+ IPC::Message* response = NULL;
+ bool succeeded = sender_->SendAndWaitForResponse(
+ new AutomationMsg_ConstrainedTitleRequest(0, handle_), &response,
+ AutomationMsg_ConstrainedTitleResponse::ID);
+
+ if (!succeeded)
+ return false;
+
+ void* iter = NULL;
+ int title_size_response = -1;
+ if (response->ReadInt(&iter, &title_size_response) &&
+ (title_size_response >= 0)) {
+ response->ReadWString(&iter, title);
+ } else {
+ succeeded = false;
+ }
+
+ delete response;
+ return succeeded;
+}
+
+bool ConstrainedWindowProxy::GetBoundsWithTimeout(gfx::Rect* bounds,
+ uint32 timeout_ms,
+ bool* is_timeout) {
+ if (!is_valid())
+ return false;
+
+ if (!bounds) {
+ NOTREACHED();
+ return false;
+ }
+
+ IPC::Message* response = NULL;
+ bool succeeded = sender_->SendAndWaitForResponseWithTimeout(
+ new AutomationMsg_ConstrainedWindowBoundsRequest(0, handle_),
+ &response,
+ AutomationMsg_ConstrainedWindowBoundsResponse::ID,
+ timeout_ms,
+ is_timeout);
+ scoped_ptr<IPC::Message> responseDeleter(response);
+ if (!succeeded)
+ return false;
+
+ Tuple2<bool, gfx::Rect> result;
+ AutomationMsg_WindowViewBoundsResponse::Read(response, &result);
+
+ *bounds = result.b;
+ return result.a;
+}
diff --git a/chrome/test/automation/constrained_window_proxy.h b/chrome/test/automation/constrained_window_proxy.h
new file mode 100644
index 0000000..f3dcb6c
--- /dev/null
+++ b/chrome/test/automation/constrained_window_proxy.h
@@ -0,0 +1,59 @@
+// 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.
+
+#ifndef CHROME_TEST_AUTOMATION_CONSTRAINED_WINDOW_PROXY_H__
+#define CHROME_TEST_AUTOMATION_CONSTRAINED_WINDOW_PROXY_H__
+
+#include <string>
+
+#include "chrome/test/automation/automation_handle_tracker.h"
+
+namespace gfx {
+class Rect;
+}
+
+class ConstrainedWindowProxy : public AutomationResourceProxy {
+public:
+ ConstrainedWindowProxy(AutomationMessageSender* sender,
+ AutomationHandleTracker* tracker,
+ int handle)
+ : AutomationResourceProxy(tracker, sender, handle) {}
+
+ virtual ~ConstrainedWindowProxy() {}
+
+ bool GetTitle(std::wstring* title) const;
+ bool GetBoundsWithTimeout(gfx::Rect* bounds,
+ uint32 timeout_ms,
+ bool* is_timeout);
+
+private:
+ DISALLOW_EVIL_CONSTRUCTORS(ConstrainedWindowProxy);
+};
+
+#endif // CHROME_TEST_AUTOMATION_CONSTRAINED_WINDOW_PROXY_H__ \ No newline at end of file
diff --git a/chrome/test/automation/tab_proxy.cc b/chrome/test/automation/tab_proxy.cc
new file mode 100644
index 0000000..4fb4432
--- /dev/null
+++ b/chrome/test/automation/tab_proxy.cc
@@ -0,0 +1,920 @@
+// 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.
+
+#include "chrome/test/automation/tab_proxy.h"
+
+#include <algorithm>
+
+#include "base/logging.h"
+#include "chrome/common/json_value_serializer.h"
+#include "chrome/test/automation/automation_constants.h"
+#include "chrome/test/automation/automation_messages.h"
+#include "chrome/test/automation/automation_proxy.h"
+#include "chrome/test/automation/constrained_window_proxy.h"
+#include "googleurl/src/gurl.h"
+
+bool TabProxy::GetTabTitle(std::wstring* title) const {
+ if (!is_valid())
+ return false;
+
+ if (!title) {
+ NOTREACHED();
+ return false;
+ }
+
+ IPC::Message* response = NULL;
+ bool succeeded = sender_->SendAndWaitForResponse(
+ new AutomationMsg_TabTitleRequest(0, handle_), &response,
+ AutomationMsg_TabTitleResponse::ID);
+
+ if (!succeeded)
+ return false;
+
+ void* iter = NULL;
+ int tab_title_size_response = -1;
+ if (response->ReadInt(&iter, &tab_title_size_response) &&
+ (tab_title_size_response >= 0)) {
+ response->ReadWString(&iter, title);
+ } else {
+ succeeded = false;
+ }
+
+ delete response;
+ return succeeded;
+}
+
+bool TabProxy::IsShelfVisible(bool* is_visible) {
+ if (!is_valid())
+ return false;
+
+ if (!is_visible) {
+ NOTREACHED();
+ return false;
+ }
+
+ IPC::Message* response = NULL;
+ bool succeeded = sender_->SendAndWaitForResponse(
+ new AutomationMsg_ShelfVisibilityRequest(0, handle_),
+ &response,
+ AutomationMsg_ShelfVisibilityResponse::ID);
+ if (!succeeded)
+ return false;
+
+ void* iter = NULL;
+ response->ReadBool(&iter, is_visible);
+ delete response;
+ return true;
+}
+
+int TabProxy::FindInPage(const std::wstring& search_string,
+ FindInPageDirection forward,
+ FindInPageCase match_case) {
+ if (!is_valid())
+ return -1;
+
+ IPC::Message* response = NULL;
+ bool succeeded = sender_->SendAndWaitForResponse(
+ new AutomationMsg_FindInPageRequest(0, handle_, search_string,
+ forward, match_case),
+ &response,
+ AutomationMsg_FindInPageResponse::ID);
+ if (!succeeded)
+ return -1;
+
+ void* iter = NULL;
+ int matches_found;
+ AutomationMsg_FindInPageResponse::Read(response, &matches_found);
+
+ return matches_found;
+}
+
+int TabProxy::NavigateToURL(const GURL& url) {
+ return NavigateToURLWithTimeout(url, INFINITE, NULL);
+}
+
+int TabProxy::NavigateToURLWithTimeout(const GURL& url,
+ uint32 timeout_ms,
+ bool* is_timeout) {
+ if (!is_valid())
+ return AUTOMATION_MSG_NAVIGATION_ERROR;
+
+ IPC::Message* response = NULL;
+ bool succeeded = sender_->SendAndWaitForResponseWithTimeout(
+ new AutomationMsg_NavigateToURLRequest(0, handle_, url), &response,
+ AutomationMsg_NavigateToURLResponse::ID, timeout_ms, is_timeout);
+
+ if (!succeeded)
+ return AUTOMATION_MSG_NAVIGATION_ERROR;
+
+ void* iter = NULL;
+ int navigate_response = AUTOMATION_MSG_NAVIGATION_ERROR;
+ response->ReadInt(&iter, &navigate_response);
+
+ delete response;
+ return navigate_response;
+}
+
+int TabProxy::NavigateInExternalTab(const GURL& url) {
+ if (!is_valid())
+ return AUTOMATION_MSG_NAVIGATION_ERROR;
+
+ IPC::Message* response = NULL;
+ bool is_timeout = false;
+ bool succeeded = sender_->SendAndWaitForResponseWithTimeout(
+ new AutomationMsg_NavigateInExternalTabRequest(0, handle_, url), &response,
+ AutomationMsg_NavigateInExternalTabResponse::ID, INFINITE, &is_timeout);
+
+ if (!succeeded)
+ return AUTOMATION_MSG_NAVIGATION_ERROR;
+
+ void* iter = NULL;
+ int navigate_response = AUTOMATION_MSG_NAVIGATION_ERROR;
+ response->ReadInt(&iter, &navigate_response);
+
+ delete response;
+ return navigate_response;
+}
+
+bool TabProxy::SetAuth(const std::wstring& username,
+ const std::wstring& password) {
+ if (!is_valid())
+ return false;
+
+ IPC::Message* response = NULL;
+ bool succeeded = sender_->SendAndWaitForResponse(
+ new AutomationMsg_SetAuthRequest(0, handle_, username, password), &response,
+ AutomationMsg_SetAuthResponse::ID);
+
+ if (!succeeded)
+ return false;
+
+ void* iter = NULL;
+ int navigate_response = -1;
+ succeeded = (response->ReadInt(&iter, &navigate_response) &&
+ navigate_response >= 0);
+
+ delete response;
+ return succeeded;
+}
+
+bool TabProxy::CancelAuth() {
+ if (!is_valid())
+ return false;
+
+ IPC::Message* response = NULL;
+ bool succeeded = sender_->SendAndWaitForResponse(
+ new AutomationMsg_CancelAuthRequest(0, handle_), &response,
+ AutomationMsg_CancelAuthResponse::ID);
+
+ if (!succeeded)
+ return false;
+
+ void* iter = NULL;
+ int navigate_response = -1;
+ succeeded = (response->ReadInt(&iter, &navigate_response) &&
+ navigate_response >= 0);
+
+ delete response;
+ return succeeded;
+}
+
+bool TabProxy::NeedsAuth() const {
+ if (!is_valid())
+ return false;
+
+ IPC::Message* response = NULL;
+ bool succeeded = sender_->SendAndWaitForResponse(
+ new AutomationMsg_NeedsAuthRequest(0, handle_), &response,
+ AutomationMsg_NeedsAuthResponse::ID);
+
+ if (!succeeded)
+ return false;
+
+ void* iter = NULL;
+ bool needs_auth = false;
+ response->ReadBool(&iter, &needs_auth);
+
+ delete response;
+ return needs_auth;
+}
+
+int TabProxy::GoBack() {
+ if (!is_valid())
+ return AUTOMATION_MSG_NAVIGATION_ERROR;
+
+ IPC::Message* response = NULL;
+ bool succeeded = sender_->SendAndWaitForResponse(
+ new AutomationMsg_GoBackRequest(0, handle_), &response,
+ AutomationMsg_GoBackResponse::ID);
+
+ if (!succeeded)
+ return AUTOMATION_MSG_NAVIGATION_ERROR;
+
+ void* iter = NULL;
+ int navigate_response = AUTOMATION_MSG_NAVIGATION_ERROR;
+ response->ReadInt(&iter, &navigate_response);
+
+ delete response;
+ return navigate_response;
+}
+
+int TabProxy::GoForward() {
+ if (!is_valid())
+ return AUTOMATION_MSG_NAVIGATION_ERROR;
+
+ IPC::Message* response = NULL;
+ bool succeeded = sender_->SendAndWaitForResponse(
+ new AutomationMsg_GoForwardRequest(0, handle_), &response,
+ AutomationMsg_GoForwardResponse::ID);
+
+ if (!succeeded)
+ return AUTOMATION_MSG_NAVIGATION_ERROR;
+
+ void* iter = NULL;
+ int navigate_response = AUTOMATION_MSG_NAVIGATION_ERROR;
+ response->ReadInt(&iter, &navigate_response);
+
+ delete response;
+ return navigate_response;
+}
+
+int TabProxy::Reload() {
+ if (!is_valid())
+ return AUTOMATION_MSG_NAVIGATION_ERROR;
+
+ IPC::Message* response = NULL;
+ bool succeeded = sender_->SendAndWaitForResponse(
+ new AutomationMsg_ReloadRequest(0, handle_), &response,
+ AutomationMsg_ReloadResponse::ID);
+
+ if (!succeeded)
+ return AUTOMATION_MSG_NAVIGATION_ERROR;
+
+ void* iter = NULL;
+ int navigate_response = AUTOMATION_MSG_NAVIGATION_ERROR;
+ response->ReadInt(&iter, &navigate_response);
+
+ delete response;
+ return navigate_response;
+}
+
+bool TabProxy::GetRedirectsFrom(const GURL& source_url,
+ std::vector<GURL>* redirects) {
+ std::vector<GURL> output;
+
+ IPC::Message* response = NULL;
+ bool succeeded = sender_->SendAndWaitForResponse(
+ new AutomationMsg_RedirectsFromRequest(0, handle_, source_url), &response,
+ AutomationMsg_RedirectsFromResponse::ID);
+ if (!succeeded)
+ return false;
+ scoped_ptr<IPC::Message> auto_deleter(response);
+
+ void* iter = NULL;
+ int num_redirects;
+ if (!response->ReadInt(&iter, &num_redirects))
+ return false;
+ if (num_redirects < 0)
+ return false; // Negative redirect counts indicate failure.
+
+ for (int i = 0; i < num_redirects; i++) {
+ GURL cur;
+ if (!IPC::ParamTraits<GURL>::Read(response, &iter, &cur))
+ return false;
+ output.push_back(cur);
+ }
+ redirects->swap(output);
+ return true;
+}
+
+bool TabProxy::GetCurrentURL(GURL* url) const {
+ if (!is_valid())
+ return false;
+
+ if (!url) {
+ NOTREACHED();
+ return false;
+ }
+
+ IPC::Message* response = NULL;
+ bool succeeded = sender_->SendAndWaitForResponse(
+ new AutomationMsg_TabURLRequest(0, handle_), &response,
+ AutomationMsg_TabURLResponse::ID);
+
+ if (!succeeded)
+ return false;
+
+ void* iter = NULL;
+ bool tab_url_success = false;
+ if (response->ReadBool(&iter, &tab_url_success) && tab_url_success) {
+ if (!IPC::ParamTraits<GURL>::Read(response, &iter, url))
+ succeeded = false;
+ } else {
+ succeeded = false;
+ }
+
+ delete response;
+ return succeeded;
+}
+
+bool TabProxy::NavigateToURLAsync(const GURL& url) {
+ if (!is_valid())
+ return false;
+
+ IPC::Message* response = NULL;
+ bool succeeded = sender_->SendAndWaitForResponse(
+ new AutomationMsg_NavigationAsyncRequest(0, handle_, url), &response,
+ AutomationMsg_NavigationAsyncResponse::ID);
+
+ if (!succeeded)
+ return false;
+
+ bool status;
+ if (AutomationMsg_NavigationAsyncResponse::Read(response, &status) &&
+ status) {
+ succeeded = true;
+ }
+
+ delete response;
+ return succeeded;
+}
+
+bool TabProxy::GetHWND(HWND* hwnd) const {
+ if (!is_valid())
+ return false;
+ if (!hwnd) {
+ NOTREACHED();
+ return false;
+ }
+ IPC::Message* response = NULL;
+ bool succeeded = sender_->SendAndWaitForResponse(
+ new AutomationMsg_TabHWNDRequest(0, handle_), &response,
+ AutomationMsg_TabHWNDResponse::ID);
+ if (!succeeded)
+ return false;
+ void* iter = NULL;
+ HWND tab_hwnd = NULL;
+ if (AutomationMsg_TabHWNDResponse::Read(response, &tab_hwnd) && tab_hwnd) {
+ *hwnd = tab_hwnd;
+ } else {
+ succeeded = false;
+ }
+
+ delete response;
+ return succeeded;
+}
+
+bool TabProxy::GetProcessID(int* process_id) const {
+ if (!is_valid())
+ return false;
+
+ if (!process_id) {
+ NOTREACHED();
+ return false;
+ }
+
+ IPC::Message* response = NULL;
+ bool succeeded = sender_->SendAndWaitForResponse(
+ new AutomationMsg_TabProcessIDRequest(0, handle_), &response,
+ AutomationMsg_TabProcessIDResponse::ID);
+
+ if (!succeeded)
+ return false;
+
+ void* iter = NULL;
+ int pid;
+ if (AutomationMsg_TabProcessIDResponse::Read(response, &pid) && (pid >= 0)) {
+ *process_id = pid;
+ } else {
+ succeeded = false;
+ }
+
+ delete response;
+ return succeeded;
+}
+
+bool TabProxy::ExecuteAndExtractString(const std::wstring& frame_xpath,
+ const std::wstring& jscript,
+ std::wstring* string_value) {
+ Value* root = NULL;
+ bool succeeded = ExecuteAndExtractValue(frame_xpath, jscript, &root);
+ if (!succeeded)
+ return false;
+
+ std::wstring read_value;
+ DCHECK(root->IsType(Value::TYPE_LIST));
+ Value* value = NULL;
+ succeeded = static_cast<ListValue*>(root)->Get(0, &value);
+ if (succeeded) {
+ succeeded = value->GetAsString(&read_value);
+ if (succeeded) {
+ string_value->swap(read_value);
+ }
+ }
+
+ delete root;
+ return succeeded;
+}
+
+bool TabProxy::ExecuteAndExtractBool(const std::wstring& frame_xpath,
+ const std::wstring& jscript,
+ bool* bool_value) {
+ Value* root = NULL;
+ bool succeeded = ExecuteAndExtractValue(frame_xpath, jscript, &root);
+ if (!succeeded)
+ return false;
+
+ bool read_value = false;
+ DCHECK(root->IsType(Value::TYPE_LIST));
+ Value* value = NULL;
+ succeeded = static_cast<ListValue*>(root)->Get(0, &value);
+ if (succeeded) {
+ succeeded = value->GetAsBoolean(&read_value);
+ if (succeeded) {
+ *bool_value = read_value;
+ }
+ }
+
+ delete value;
+ return succeeded;
+}
+
+bool TabProxy::ExecuteAndExtractInt(const std::wstring& frame_xpath,
+ const std::wstring& jscript,
+ int* int_value) {
+ Value* root = NULL;
+ bool succeeded = ExecuteAndExtractValue(frame_xpath, jscript, &root);
+ if (!succeeded)
+ return false;
+
+ int read_value = 0;
+ DCHECK(root->IsType(Value::TYPE_LIST));
+ Value* value = NULL;
+ succeeded = static_cast<ListValue*>(root)->Get(0, &value);
+ if (succeeded) {
+ succeeded = value->GetAsInteger(&read_value);
+ if (succeeded) {
+ *int_value = read_value;
+ }
+ }
+
+ delete value;
+ return succeeded;
+}
+
+bool TabProxy::ExecuteAndExtractValue(const std::wstring& frame_xpath,
+ const std::wstring& jscript,
+ Value** value) {
+ if (!is_valid())
+ return false;
+
+ if (!value) {
+ NOTREACHED();
+ return false;
+ }
+
+ IPC::Message* response = NULL;
+ bool succeeded = sender_->SendAndWaitForResponse(
+ new AutomationMsg_DomOperationRequest(0, handle_, frame_xpath, jscript),
+ &response, AutomationMsg_DomOperationResponse::ID);
+
+ void* iter = NULL;
+ std::string json;
+ succeeded = response->ReadString(&iter, &json);
+ if (!succeeded) {
+ delete response;
+ return false;
+ }
+ // Wrap |json| in an array before deserializing because valid JSON has an
+ // array or an object as the root.
+ json.insert(0, "[");
+ json.append("]");
+
+ JSONStringValueSerializer deserializer(json);
+ succeeded = deserializer.Deserialize(value);
+
+ delete response;
+ return succeeded;
+}
+
+bool TabProxy::GetConstrainedWindowCount(int* count) const {
+ if (!is_valid())
+ return false;
+
+ if (!count) {
+ NOTREACHED();
+ return false;
+ }
+
+ IPC::Message* response = NULL;
+ bool succeeded = sender_->SendAndWaitForResponse(
+ new AutomationMsg_ConstrainedWindowCountRequest(0, handle_),
+ &response, AutomationMsg_ConstrainedWindowCountResponse::ID);
+
+ void* iter = NULL;
+ int count_response = -1;
+ if (response->ReadInt(&iter, &count_response) &&
+ (count_response >= 0)) {
+ *count = count_response;
+ } else {
+ succeeded = false;
+ }
+
+ delete response;
+ return succeeded;
+}
+
+ConstrainedWindowProxy* TabProxy::GetConstrainedWindow(
+ int window_index) const {
+ if (!is_valid())
+ return NULL;
+
+ IPC::Message* response = NULL;
+ bool succeeded = sender_->SendAndWaitForResponse(
+ new AutomationMsg_ConstrainedWindowRequest(0, handle_, window_index),
+ &response, AutomationMsg_ConstrainedWindowResponse::ID);
+ if (!succeeded)
+ return NULL;
+
+ void* iter = NULL;
+ int handle;
+
+ scoped_ptr<IPC::Message> response_deleter(response); // Ensure deleted.
+ if (response->ReadInt(&iter, &handle) && (handle != 0))
+ return new ConstrainedWindowProxy(sender_, tracker_, handle);
+ return NULL;
+}
+
+bool TabProxy::WaitForChildWindowCountToChange(int count, int* new_count,
+ int wait_timeout) {
+ int intervals = std::min(wait_timeout/automation::kSleepTime, 1);
+ for (int i = 0; i < intervals; ++i) {
+ Sleep(automation::kSleepTime);
+ bool succeeded = GetConstrainedWindowCount(new_count);
+ if (!succeeded) return false;
+ if (count != *new_count) return true;
+ }
+ // Constrained Window count did not change, return false.
+ return false;
+}
+
+bool TabProxy::GetCookies(const GURL& url, std::string* cookies) {
+ if (!is_valid())
+ return false;
+
+ IPC::Message* response = NULL;
+ bool succeeded = sender_->SendAndWaitForResponse(
+ new AutomationMsg_GetCookiesRequest(0, url, handle_), &response,
+ AutomationMsg_GetCookiesResponse::ID);
+
+ if (succeeded) {
+ void* iter = NULL;
+ int size;
+ std::string local_value;
+
+ if (response->ReadInt(&iter, &size) && size >=0) {
+ if (!response->ReadString(&iter, cookies)) {
+ succeeded = false;
+ }
+ } else {
+ succeeded = false;
+ }
+ }
+
+ delete response;
+ return succeeded;
+}
+
+bool TabProxy::GetCookieByName(const GURL& url,
+ const std::string& name,
+ std::string* cookie) {
+ std::string cookies;
+ if (!GetCookies(url, &cookies))
+ return false;
+
+ std::string namestr = name + "=";
+ std::string::size_type idx = cookies.find(namestr);
+ if (idx != std::string::npos) {
+ cookies.erase(0, idx + namestr.length());
+ *cookie = cookies.substr(0, cookies.find(";"));
+ } else {
+ cookie->clear();
+ }
+
+ return true;
+}
+
+bool TabProxy::SetCookie(const GURL& url, const std::string& value) {
+ IPC::Message* response = NULL;
+ bool succeeded = sender_->SendAndWaitForResponse(
+ new AutomationMsg_SetCookieRequest(0, url, value, handle_), &response,
+ AutomationMsg_SetCookieResponse::ID);
+ if (!succeeded)
+ return false;
+
+ void* iter = NULL;
+ int response_value;
+
+ if (!response->ReadInt(&iter, &response_value) || response_value < 0) {
+ succeeded = false;
+ }
+
+ delete response;
+ return succeeded;
+}
+
+int TabProxy::InspectElement(int x, int y) {
+ if (!is_valid())
+ return -1;
+
+ IPC::Message* response = NULL;
+ bool succeeded = sender_->SendAndWaitForResponse(
+ new AutomationMsg_InspectElementRequest(0, handle_, x, y),
+ &response, AutomationMsg_InspectElementResponse::ID);
+ if (!succeeded)
+ return -1;
+
+ int ret;
+ AutomationMsg_InspectElementResponse::Read(response, &ret);
+ return ret;
+}
+
+bool TabProxy::GetDownloadDirectory(std::wstring* download_directory) {
+ DCHECK(download_directory);
+ if (!is_valid())
+ return false;
+
+ IPC::Message* response = NULL;
+ bool succeeded =
+ sender_->SendAndWaitForResponse(
+ new AutomationMsg_DownloadDirectoryRequest(0, handle_),
+ &response,
+ AutomationMsg_DownloadDirectoryResponse::ID);
+ if (!succeeded)
+ return false;
+
+ void* iter = NULL;
+ response->ReadWString(&iter, download_directory);
+ delete response;
+ return true;
+}
+
+bool TabProxy::ShowInterstitialPage(const std::string& html_text) {
+ if (!is_valid())
+ return false;
+
+ const int kTimeout = 2000;
+ bool is_timeout = false;
+ IPC::Message* response = NULL;
+ bool succeeded = sender_->SendAndWaitForResponseWithTimeout(
+ new AutomationMsg_ShowInterstitialPageRequest(0, handle_, html_text),
+ &response,
+ AutomationMsg_ShowInterstitialPageResponse::ID, kTimeout, &is_timeout);
+
+ if (!succeeded || !is_timeout)
+ return false;
+
+ void* iter = NULL;
+ bool result = true;
+ response->ReadBool(&iter, &result);
+
+ delete response;
+ return result;
+}
+
+bool TabProxy::HideInterstitialPage() {
+ if (!is_valid())
+ return false;
+
+ IPC::Message* response = NULL;
+ bool succeeded =
+ sender_->SendAndWaitForResponse(
+ new AutomationMsg_HideInterstitialPageRequest(0, handle_),
+ &response,
+ AutomationMsg_HideInterstitialPageResponse::ID);
+
+ if (!succeeded)
+ return false;
+
+ void* iter = NULL;
+ bool result = true;
+ response->ReadBool(&iter, &result);
+
+ delete response;
+ return result;
+}
+
+bool TabProxy::Close() {
+ return Close(false);
+}
+
+bool TabProxy::Close(bool wait_until_closed) {
+ if (!is_valid())
+ return false;
+
+ IPC::Message* response = NULL;
+ bool succeeded =
+ sender_->SendAndWaitForResponse(
+ new AutomationMsg_CloseTabRequest(0, handle_, wait_until_closed),
+ &response,
+ AutomationMsg_CloseTabResponse::ID);
+
+ if (!succeeded)
+ return false;
+
+ void* iter = NULL;
+ bool result = true;
+ response->ReadBool(&iter, &result);
+
+ delete response;
+ return result;
+}
+
+bool TabProxy::SetAccelerators(HACCEL accel_table,
+ int accel_table_entry_count) {
+ if (!is_valid())
+ return false;
+
+ IPC::Message* response = NULL;
+ bool is_timeout = false;
+ bool succeeded = sender_->SendAndWaitForResponseWithTimeout(
+ new AutomationMsg_SetAcceleratorsForTab(0, handle_, accel_table,
+ accel_table_entry_count),
+ &response,
+ AutomationMsg_SetAcceleratorsForTabResponse::ID, INFINITE, &is_timeout);
+
+ if (!succeeded)
+ return AUTOMATION_MSG_NAVIGATION_ERROR;
+
+ void* iter = NULL;
+ bool set_accel_response = false;
+ response->ReadBool(&iter, &set_accel_response);
+
+ delete response;
+ return set_accel_response;
+}
+
+bool TabProxy::ProcessUnhandledAccelerator(const MSG& msg) {
+ if (!is_valid())
+ return false;
+ return sender_->Send(
+ new AutomationMsg_ProcessUnhandledAccelerator(0, handle_, msg));
+ // This message expects no response
+}
+
+bool TabProxy::WaitForTabToBeRestored() {
+ if (!is_valid())
+ return false;
+ IPC::Message* response = NULL;
+ return sender_->SendAndWaitForResponse(
+ new AutomationMsg_WaitForTabToBeRestored(0, handle_), &response,
+ AutomationMsg_TabFinishedRestoring::ID);
+}
+
+bool TabProxy::GetSecurityState(SecurityStyle* security_style,
+ int* ssl_cert_status,
+ int* mixed_content_state) {
+ DCHECK(security_style && ssl_cert_status && mixed_content_state);
+
+ if (!is_valid())
+ return false;
+
+ IPC::Message* response = NULL;
+ bool is_timeout = false;
+ bool succeeded = sender_->SendAndWaitForResponseWithTimeout(
+ new AutomationMsg_GetSecurityState(0, handle_),
+ &response,
+ AutomationMsg_GetSecurityStateResponse::ID, INFINITE, &is_timeout);
+ scoped_ptr<IPC::Message> auto_deleter(response);
+
+ if (!succeeded)
+ return false;
+
+ void* iter = NULL;
+ int value;
+
+ response->ReadBool(&iter, &succeeded);
+ if (!succeeded)
+ return false;
+ response->ReadInt(&iter, &value);
+ *security_style = static_cast<SecurityStyle>(value);
+ response->ReadInt(&iter, ssl_cert_status);
+ response->ReadInt(&iter, mixed_content_state);
+
+ return true;
+}
+
+bool TabProxy::GetPageType(NavigationEntry::PageType* page_type) {
+ DCHECK(page_type);
+
+ if (!is_valid())
+ return false;
+
+ IPC::Message* response = NULL;
+ bool is_timeout = false;
+ bool succeeded = sender_->SendAndWaitForResponseWithTimeout(
+ new AutomationMsg_GetPageType(0, handle_),
+ &response,
+ AutomationMsg_GetPageTypeResponse::ID, INFINITE, &is_timeout);
+ scoped_ptr<IPC::Message> auto_deleter(response);
+
+ if (!succeeded)
+ return false;
+
+ void* iter = NULL;
+ int value;
+ response->ReadBool(&iter, &succeeded);
+ if (!succeeded)
+ return false;
+ response->ReadInt(&iter, &value);
+ *page_type = static_cast<NavigationEntry::PageType>(value);
+ return true;
+}
+
+bool TabProxy::TakeActionOnSSLBlockingPage(bool proceed) {
+ if (!is_valid())
+ return false;
+
+ IPC::Message* response = NULL;
+ bool is_timeout = false;
+ bool succeeded = sender_->SendAndWaitForResponseWithTimeout(
+ new AutomationMsg_ActionOnSSLBlockingPage(0, handle_, proceed),
+ &response,
+ AutomationMsg_ActionOnSSLBlockingPageResponse::ID, INFINITE, &is_timeout);
+ scoped_ptr<IPC::Message> auto_deleter(response);
+
+ if (!succeeded)
+ return false;
+
+ void* iter = NULL;
+ bool status = false;
+ response->ReadBool(&iter, &status);
+
+ return status;
+}
+
+bool TabProxy::PrintNow() {
+ if (!is_valid())
+ return false;
+
+ IPC::Message* response = NULL;
+ bool succeeded = sender_->SendAndWaitForResponse(
+ new AutomationMsg_PrintNowRequest(0, handle_), &response,
+ AutomationMsg_PrintNowResponse::ID);
+ scoped_ptr<IPC::Message> auto_deleter(response);
+ if (!succeeded)
+ return false;
+
+ void* iter = NULL;
+ succeeded = false;
+ return response->ReadBool(&iter, &succeeded) && succeeded;
+}
+
+bool TabProxy::SavePage(const std::wstring& file_name,
+ const std::wstring& dir_path,
+ SavePackage::SavePackageType type) {
+ if (!is_valid())
+ return false;
+
+ IPC::Message* response = NULL;
+ bool succeeded = sender_->SendAndWaitForResponse(
+ new AutomationMsg_SavePageRequest(0, handle_, file_name,
+ dir_path, static_cast<int>(type)),
+ &response,
+ AutomationMsg_SavePageResponse::ID);
+
+ if (!succeeded)
+ return false;
+
+ void* iter = NULL;
+ response->ReadBool(&iter, &succeeded);
+ delete response;
+
+ return succeeded;
+}
diff --git a/chrome/test/automation/tab_proxy.h b/chrome/test/automation/tab_proxy.h
new file mode 100644
index 0000000..712ab9c
--- /dev/null
+++ b/chrome/test/automation/tab_proxy.h
@@ -0,0 +1,266 @@
+// 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.
+
+#ifndef CHROME_TEST_AUTOMATION_TAB_PROXY_H__
+#define CHROME_TEST_AUTOMATION_TAB_PROXY_H__
+
+#include <wtypes.h>
+#include <string>
+#include <vector>
+
+#include "chrome/browser/security_style.h"
+#include "chrome/browser/navigation_entry.h"
+#include "chrome/browser/save_package.h"
+#include "chrome/test/automation/automation_handle_tracker.h"
+
+class ConstrainedWindowProxy;
+class GURL;
+class Value;
+
+typedef enum FindInPageDirection { BACK = 0, FWD = 1 };
+typedef enum FindInPageCase { IGNORE_CASE = 0, CASE_SENSITIVE = 1 };
+
+class TabProxy : public AutomationResourceProxy {
+ public:
+ TabProxy(AutomationMessageSender* sender,
+ AutomationHandleTracker* tracker,
+ int handle)
+ : AutomationResourceProxy(tracker, sender, handle) {}
+
+ virtual ~TabProxy() {}
+
+ // Gets the current url of the tab.
+ bool GetCurrentURL(GURL* url) const;
+
+ // Gets the title of the tab.
+ bool GetTabTitle(std::wstring* title) const;
+
+ // Gets the number of constrained window for this tab.
+ bool GetConstrainedWindowCount(int* count) const;
+
+ // Gets the proxy object for constrained window within this tab. Ownership
+ // for the returned object is transfered to the caller. Returns NULL on
+ // failure.
+ ConstrainedWindowProxy* GetConstrainedWindow(int window_index) const;
+
+ // Execute a javascript in a frame's context whose xpath
+ // is provided as the first parameter and extract
+ // the values from the resulting json string.
+ // Example:
+ // jscript = "window.domAutomationController.send('string');"
+ // will result in value = "string"
+ // jscript = "window.domAutomationController.send(24);"
+ // will result in value = 24
+ bool ExecuteAndExtractString(const std::wstring& frame_xpath,
+ const std::wstring& jscript,
+ std::wstring* value);
+ bool ExecuteAndExtractBool(const std::wstring& frame_xpath,
+ const std::wstring& jscript,
+ bool* value);
+ bool ExecuteAndExtractInt(const std::wstring& frame_xpath,
+ const std::wstring& jscript,
+ int* value);
+ bool ExecuteAndExtractValue(const std::wstring& frame_xpath,
+ const std::wstring& jscript,
+ Value** value);
+
+ // Navigates to a url. This method accepts the same kinds of URL input that
+ // can be passed to Chrome on the command line. This is a synchronous call and
+ // hence blocks until the navigation completes.
+ // Returns a status from AutomationMsg_NavigationResponseValues.
+ int NavigateToURL(const GURL& url);
+
+ // Navigates to a url. This is same as NavigateToURL with a timeout option.
+ // The function returns until the navigation completes or timeout (in
+ // milliseconds) occurs. If return after timeout, is_timeout is set to true.
+ int NavigateToURLWithTimeout(const GURL& url, uint32 timeout_ms,
+ bool* is_timeout);
+
+ // Navigates to a url in an externally hosted tab.
+ // This method accepts the same kinds of URL input that
+ // can be passed to Chrome on the command line. This is a synchronous call and
+ // hence blocks until the navigation completes.
+ // Returns a status from AutomationMsg_NavigationResponseValues.
+ int NavigateInExternalTab(const GURL& url);
+
+ // Navigates to a url. This is an asynchronous version of NavigateToURL.
+ // The function returns immediately after sending the LoadURL notification
+ // to the browser.
+ // TODO(vibhor): Add a callback if needed in future.
+ // TODO(mpcomplete): If the navigation results in an auth challenge, the
+ // TabProxy we attach won't know about it. See bug 666730.
+ bool NavigateToURLAsync(const GURL& url);
+
+ // Replaces a vector contents with the redirect chain out of the given URL.
+ // Returns true on success. Failure may be due to being unable to send the
+ // message, parse the response, or a failure of the history system in the
+ // browser.
+ bool GetRedirectsFrom(const GURL& source_url, std::vector<GURL>* redirects);
+
+ // Equivalent to hitting the Back button. This is a synchronous call and
+ // hence blocks until the navigation completes.
+ int GoBack();
+
+ // Equivalent to hitting the Forward button. This is a synchronous call and
+ // hence blocks until the navigation completes.
+ // Returns a status from AutomationMsg_NavigationResponseValues.
+ int GoForward();
+
+ // Equivalent to hitting the Reload button. This is a synchronous call and
+ // hence blocks until the navigation completes.
+ int Reload();
+
+ // Closes the tab. This is synchronous, but does NOT block until the tab has
+ // closed, rather it blocks until the browser has initiated the close. Use
+ // Close(true) if you need to block until tab completely closes.
+ //
+ // Note that this proxy is invalid after this call.
+ bool Close();
+
+ // Variant of close that allows you to specify whether you want to block
+ // until the tab has completely closed (wait_until_closed == true) or block
+ // until the browser has initiated the close (wait_until_closed = false).
+ //
+ // When a tab is closed the browser does additional work via invoke later
+ // and may wait for messages from the renderer. Supplying a value of true to
+ // this method waits until all processing is done. Be careful with this,
+ // when closing the last tab it is possible for the browser to shutdown BEFORE
+ // the tab has completely closed. In other words, this may NOT be sent for
+ // the last tab.
+ bool Close(bool wait_until_closed);
+
+ // Gets the HWND that corresponds to the content area of this tab.
+ // Returns true if the call was successful.
+ // Returns a status from AutomationMsg_NavigationResponseValues.
+ bool GetHWND(HWND* hwnd) const;
+
+ // Gets the process ID that corresponds to the content area of this tab.
+ // Returns true if the call was successful. If the specified tab has no
+ // separate process for rendering its content, the return value is true but
+ // the process_id is 0.
+ bool GetProcessID(int* process_id) const;
+
+ // Supply or cancel authentication to a login prompt. These are synchronous
+ // calls and hence block until the load finishes (or another login prompt
+ // appears, in the case of invalid login info).
+ bool SetAuth(const std::wstring& username, const std::wstring& password);
+ bool CancelAuth();
+
+ // Checks if this tab has a login prompt waiting for auth. This will be
+ // true if a navigation results in a login prompt, and if an attempted login
+ // fails.
+ // Note that this is only valid if you've done a navigation on this same
+ // object; different TabProxy objects can refer to the same Tab. Calls
+ // that can set this are NavigateToURL, GoBack, and GoForward.
+ // TODO(mpcomplete): we have no way of knowing if auth is needed after either
+ // NavigateToURLAsync, or after appending a tab with an URL that triggers
+ // auth.
+ bool NeedsAuth() const;
+
+ // Fills |*is_visible| with whether the tab's download shelf is currently
+ // visible. The return value indicates success. On failure, |*is_visible| is
+ // unchanged.
+ bool IsShelfVisible(bool* is_visible);
+
+ // Starts a search within the current tab. The parameter 'search_string'
+ // specifies what string to search for, 'forward' specifies whether to search
+ // in forward direction, and 'match_case' specifies case sensitivity
+ // (true=case sensitive). A return value of -1 indicates failure.
+ int FindInPage(const std::wstring& search_string, FindInPageDirection forward,
+ FindInPageCase match_case);
+
+ bool GetCookies(const GURL& url, std::string* cookies);
+ bool GetCookieByName(const GURL& url,
+ const std::string& name,
+ std::string* cookies);
+ bool SetCookie(const GURL& url, const std::string& value);
+
+ // Sends a InspectElement message for the current tab. |x| and |y| are the
+ // coordinates that we want to simulate that the user is trying to inspect.
+ int InspectElement(int x, int y);
+
+ // Block the thread until the constrained(child) window count changes.
+ // First parameter is the original child window count
+ // The second parameter is updated with the number of new child windows.
+ // The third parameter specifies the timeout length for the wait loop.
+ // Returns false if the count does not change.
+ bool WaitForChildWindowCountToChange(int count, int* new_count,
+ int wait_timeout);
+
+ bool GetDownloadDirectory(std::wstring* download_directory);
+
+ // Shows an interstitial page. Blocks until the interstitial page
+ // has been loaded. Return false if a failure happens.3
+ bool ShowInterstitialPage(const std::string& html_text);
+
+ // Hides the currently shown interstitial page. Blocks until the interstitial
+ // page has been hidden. Return false if a failure happens.
+ bool HideInterstitialPage();
+
+ // This sets the keyboard accelerators to be used by an externally
+ // hosted tab. This call is not valid on a regular tab hosted within
+ // Chrome.
+ bool SetAccelerators(HACCEL accel_table, int accel_table_entry_count);
+
+ // The container of an externally hosted tab calls this to reflect any
+ // accelerator keys that it did not process. This gives the tab a chance
+ // to handle the keys
+ bool ProcessUnhandledAccelerator(const MSG& msg);
+
+ bool WaitForTabToBeRestored();
+
+ // Retrieves the different security states for the current tab.
+ bool GetSecurityState(SecurityStyle* security_style,
+ int* ssl_cert_status,
+ int* mixed_content_state);
+
+ // Returns the type of the page currently showing (normal, interstitial,
+ // error).
+ bool GetPageType(NavigationEntry::PageType* page_type);
+
+ // Simulates the user action on the SSL blocking page. if |proceed| is true,
+ // this is equivalent to clicking the 'Proceed' button, if false to 'Take me
+ // out of there' button.
+ bool TakeActionOnSSLBlockingPage(bool proceed);
+
+ // Prints the current page without user intervention.
+ bool PrintNow();
+
+ // Save the current web page. |file_name| is the HTML file name, and
+ // |dir_path| is the directory for saving resource files. |type| indicates
+ // which type we're saving as: HTML only or the complete web page.
+ bool SavePage(const std::wstring& file_name,
+ const std::wstring& dir_path,
+ SavePackage::SavePackageType type);
+
+ private:
+ DISALLOW_EVIL_CONSTRUCTORS(TabProxy);
+};
+
+#endif // CHROME_TEST_AUTOMATION_TAB_PROXY_H__
diff --git a/chrome/test/automation/ui_controls.cc b/chrome/test/automation/ui_controls.cc
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/chrome/test/automation/ui_controls.cc
diff --git a/chrome/test/automation/ui_controls.h b/chrome/test/automation/ui_controls.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/chrome/test/automation/ui_controls.h
diff --git a/chrome/test/automation/window_proxy.cc b/chrome/test/automation/window_proxy.cc
new file mode 100644
index 0000000..5f647d2
--- /dev/null
+++ b/chrome/test/automation/window_proxy.cc
@@ -0,0 +1,187 @@
+// 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.
+
+#include "chrome/test/automation/window_proxy.h"
+
+#include <vector>
+#include <algorithm>
+
+#include "base/gfx/rect.h"
+#include "base/logging.h"
+#include "chrome/test/automation/automation_constants.h"
+#include "chrome/test/automation/automation_messages.h"
+#include "chrome/test/automation/automation_proxy.h"
+#include "chrome/test/automation/browser_proxy.h"
+#include "chrome/test/automation/tab_proxy.h"
+#include "googleurl/src/gurl.h"
+
+bool WindowProxy::GetHWND(HWND* handle) const {
+ if (!is_valid()) return false;
+
+ if (!handle) {
+ NOTREACHED();
+ return false;
+ }
+
+ IPC::Message* response = NULL;
+ bool succeeded = sender_->SendAndWaitForResponse(
+ new AutomationMsg_WindowHWNDRequest(0, handle_), &response,
+ AutomationMsg_WindowHWNDResponse::ID);
+ if (!succeeded)
+ return false;
+
+ HWND hwnd_response;
+ if (AutomationMsg_WindowHWNDResponse::Read(response, &hwnd_response) &&
+ hwnd_response) {
+ *handle = hwnd_response;
+ } else {
+ succeeded = false;
+ }
+
+ delete response;
+ return succeeded;
+}
+
+bool WindowProxy::SimulateOSClick(const POINT& click, int flags) {
+ if (!is_valid()) return false;
+
+ return sender_->Send(
+ new AutomationMsg_WindowClickRequest(0, handle_, click, flags));
+}
+
+bool WindowProxy::SimulateOSKeyPress(wchar_t key, int flags) {
+ if (!is_valid()) return false;
+
+ return sender_->Send(
+ new AutomationMsg_WindowKeyPressRequest(0, handle_, key, flags));
+}
+
+bool WindowProxy::SetVisible(bool visible) {
+ if (!is_valid()) return false;
+
+ IPC::Message* response = NULL;
+ bool succeeded = sender_->SendAndWaitForResponse(
+ new AutomationMsg_SetWindowVisibleRequest(0, handle_, visible),
+ &response, AutomationMsg_SetWindowVisibleResponse::ID);
+
+ scoped_ptr<IPC::Message> response_deleter(response); // Ensure deleted.
+ if (!succeeded)
+ return false;
+
+ void* iter = NULL;
+ if (!response->ReadBool(&iter, &succeeded))
+ succeeded = false;
+
+ return succeeded;
+}
+
+bool WindowProxy::IsActive(bool* active) {
+ if (!is_valid()) return false;
+
+ IPC::Message* response = NULL;
+ bool succeeded = sender_->SendAndWaitForResponse(
+ new AutomationMsg_IsWindowActiveRequest(0, handle_),
+ &response, AutomationMsg_IsWindowActiveResponse::ID);
+
+ scoped_ptr<IPC::Message> response_deleter(response); // Ensure deleted.
+ if (!succeeded)
+ return false;
+
+ void* iter = NULL;
+ if (!response->ReadBool(&iter, &succeeded) || !succeeded)
+ return false;
+
+ if (!response->ReadBool(&iter, active))
+ return false;
+
+ return true;
+}
+
+bool WindowProxy::Activate() {
+ if (!is_valid()) return false;
+
+ return sender_->Send(new AutomationMsg_ActivateWindow(0, handle_));
+}
+
+bool WindowProxy::GetViewBounds(int view_id, gfx::Rect* bounds,
+ bool screen_coordinates) {
+ return GetViewBoundsWithTimeout(view_id, bounds, screen_coordinates,
+ INFINITE, NULL);
+}
+
+bool WindowProxy::GetViewBoundsWithTimeout(int view_id, gfx::Rect* bounds,
+ bool screen_coordinates,
+ uint32 timeout_ms,
+ bool* is_timeout) {
+ if (!is_valid()) return false;
+
+ if (!bounds) {
+ NOTREACHED();
+ return false;
+ }
+
+ IPC::Message* response = NULL;
+ bool succeeded = sender_->SendAndWaitForResponseWithTimeout(
+ new AutomationMsg_WindowViewBoundsRequest(0, handle_, view_id,
+ screen_coordinates),
+ &response,
+ AutomationMsg_WindowViewBoundsResponse::ID,
+ timeout_ms,
+ is_timeout);
+ if (!succeeded)
+ return false;
+
+ Tuple2<bool, gfx::Rect> result;
+ AutomationMsg_WindowViewBoundsResponse::Read(response, &result);
+
+ *bounds = result.b;
+ return result.a;
+}
+
+bool WindowProxy::GetFocusedViewID(int* view_id) {
+ if (!is_valid()) return false;
+
+ if (!view_id) {
+ NOTREACHED();
+ return false;
+ }
+
+ IPC::Message* response = NULL;
+ bool succeeded = sender_->SendAndWaitForResponse(
+ new AutomationMsg_GetFocusedViewIDRequest(0, handle_),
+ &response,
+ AutomationMsg_GetFocusedViewIDResponse::ID);
+
+ *view_id = -1;
+ if (succeeded &&
+ AutomationMsg_GetFocusedViewIDResponse::Read(response, view_id))
+ return true;
+
+ return false;
+} \ No newline at end of file
diff --git a/chrome/test/automation/window_proxy.h b/chrome/test/automation/window_proxy.h
new file mode 100644
index 0000000..9fe7740
--- /dev/null
+++ b/chrome/test/automation/window_proxy.h
@@ -0,0 +1,106 @@
+// 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.
+
+#ifndef CHROME_TEST_AUTOMATION_WINDOW_PROXY_H__
+#define CHROME_TEST_AUTOMATION_WINDOW_PROXY_H__
+
+#include <string>
+#include "base/thread.h"
+#include "chrome/test/automation/automation_handle_tracker.h"
+
+class GURL;
+class BrowserProxy;
+class TabProxy;
+class WindowProxy;
+
+namespace gfx {
+ class Rect;
+}
+
+// This class presents the interface to actions that can be performed on a given
+// window. Note that this object can be invalidated at any time if the
+// corresponding window in the app is closed. In that case, any subsequent
+// calls will return false immediately.
+class WindowProxy : public AutomationResourceProxy {
+ public:
+ WindowProxy(AutomationMessageSender* sender,
+ AutomationHandleTracker* tracker,
+ int handle)
+ : AutomationResourceProxy(tracker, sender, handle) {}
+ virtual ~WindowProxy() {}
+
+ // Gets the outermost HWND that corresponds to the given window.
+ // Returns true if the call was successful.
+ bool GetHWND(HWND* handle) const;
+
+ // Simulates a click at the OS level. |click| is in the window's coordinates
+ // and |flags| specifies which buttons are pressed (as defined in
+ // chrome/views/event.h). Note that this is equivalent to the user moving
+ // the mouse and pressing the button. So if there is a window on top of this
+ // window, the top window is clicked.
+ bool SimulateOSClick(const POINT& click, int flags);
+
+ // Simulates a key press at the OS level. |key| is the key pressed and
+ // |flags| specifies which modifiers keys are also pressed (as defined in
+ // chrome/views/event.h). Note that this actually sends the event to the
+ // window that has focus.
+ bool SimulateOSKeyPress(wchar_t key, int flags);
+
+ // Shows/hides the window and as a result makes it active/inactive.
+ // Returns true if the call was successful.
+ bool SetVisible(bool visible);
+
+ // Sets |active| to true if this view is currently the active window.
+ // Returns true if the call was successful.
+ bool IsActive(bool* active);
+
+ // Make this window the active window.
+ // Returns true if the call was successful.
+ bool Activate();
+
+ // Gets the bounds (in window coordinates) that correspond to the view with
+ // the given ID in this window. Returns true if bounds could be obtained.
+ // If |screen_coordinates| is true, the bounds are returned in the coordinates
+ // of the screen, if false in the coordinates of the browser.
+ bool GetViewBounds(int view_id, gfx::Rect* bounds, bool screen_coordinates);
+
+ // Like GetViewBounds except returns false if timeout occurs before view
+ // bounds are obtained, and sets is_timeout accordingly.
+ bool GetViewBoundsWithTimeout(int view_id, gfx::Rect* bounds,
+ bool screen_coordinates, uint32 timeout_ms,
+ bool* is_timeout);
+ // Gets the id of the view that currently has focus. Returns true if the id
+ // was retrieved.
+ bool GetFocusedViewID(int* view_id);
+
+ private:
+ DISALLOW_EVIL_CONSTRUCTORS(WindowProxy);
+};
+
+#endif // CHROME_TEST_AUTOMATION_WINDOW_PROXY_H__
diff --git a/chrome/test/chrome_plugin/SConscript b/chrome/test/chrome_plugin/SConscript
new file mode 100644
index 0000000..af55a6d
--- /dev/null
+++ b/chrome/test/chrome_plugin/SConscript
@@ -0,0 +1,98 @@
+# 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.
+
+Import('env')
+
+env = env.Clone()
+
+
+env.Prepend(
+ CPPPATH = [
+ '#/..',
+ ],
+ LINKFLAGS = [
+ '/INCREMENTAL',
+
+ '/MANIFEST',
+ '/DELAYLOAD:"dwmapi.dll"',
+ '/DELAYLOAD:"uxtheme.dll"',
+ '/MACHINE:X86',
+ '/FIXED:No',
+
+ '/safeseh',
+ '/dynamicbase',
+ '/ignore:4199',
+ '/nxcompat',
+
+ '/DEBUG',
+ ],
+ LIBS = [
+ 'winmm.lib',
+
+ 'wininet.lib',
+ 'version.lib',
+ 'msimg32.lib',
+ 'ws2_32.lib',
+ 'usp10.lib',
+ 'psapi.lib',
+ 'kernel32.lib',
+ 'user32.lib',
+ 'gdi32.lib',
+ 'winspool.lib',
+ 'comdlg32.lib',
+ 'advapi32.lib',
+ 'shell32.lib',
+ 'ole32.lib',
+ 'oleaut32.lib',
+ 'uuid.lib',
+ 'odbc32.lib',
+ 'odbccp32.lib',
+
+ 'DelayImp.lib',
+ ],
+)
+
+#/MANIFESTFILE:"C:\src\trunk-vs\chrome\Debug\obj\test_chrome_plugin\test_chrome_plugin.dll.intermediate.manifest"
+#/PDB:"c:\src\trunk-vs\chrome\Debug\test_chrome_plugin.pdb"
+
+input_files = [
+ 'test_chrome_plugin.cc',
+ 'test_chrome_plugin.def',
+]
+
+libs = [
+ '$GOOGLEURL_DIR/googleurl.lib',
+ '$ICU38_DIR/icuuc.lib',
+ '$BASE_DIR/base.lib',
+]
+
+dll = env.SharedLibrary('test_chrome_plugin', input_files + libs)
+
+i = env.Install('$TARGET_ROOT', dll)
+env.Alias('chrome', i)
diff --git a/chrome/test/chrome_plugin/test_chrome_plugin.cc b/chrome/test/chrome_plugin/test_chrome_plugin.cc
new file mode 100644
index 0000000..3264287
--- /dev/null
+++ b/chrome/test/chrome_plugin/test_chrome_plugin.cc
@@ -0,0 +1,401 @@
+// 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.
+
+#include "chrome/test/chrome_plugin/test_chrome_plugin.h"
+
+#include "base/basictypes.h"
+#include "base/logging.h"
+#include "base/message_loop.h"
+#include "base/string_util.h"
+#include "chrome/common/chrome_plugin_api.h"
+
+static CPID g_cpid;
+static CPBrowserFuncs g_cpbrowser_funcs;
+static CPRequestFuncs g_cprequest_funcs;
+static CPResponseFuncs g_cpresponse_funcs;
+static TestFuncParams::BrowserFuncs g_cptest_funcs;
+
+const TestResponsePayload* FindPayload(const char* url) {
+ for (int i = 0; i < arraysize(kChromeTestPluginPayloads); ++i) {
+ if (strcmp(kChromeTestPluginPayloads[i].url, url) == 0)
+ return &kChromeTestPluginPayloads[i];
+ }
+ return NULL;
+}
+
+std::string GetPayloadHeaders(const TestResponsePayload* payload) {
+ return StringPrintf(
+ "HTTP/1.1 200 OK%c"
+ "Content-type: %s%c"
+ "%c", 0, payload->mime_type, 0, 0);
+}
+
+void STDCALL InvokeLaterCallback(void* data) {
+ Task* task = static_cast<Task*>(data);
+ task->Run();
+ delete task;
+}
+
+// ResponseStream: Manages the streaming of the payload data.
+
+class ResponseStream : public base::RefCounted<ResponseStream> {
+public:
+ ResponseStream(const TestResponsePayload* payload, CPRequest* request);
+ ~ResponseStream() {
+ request_->pdata = NULL;
+ }
+
+ void Init();
+ int GetResponseInfo(CPResponseInfoType type, void* buf, uint32 buf_size);
+ int ReadData(void* buf, uint32 buf_size);
+
+private:
+ // Called asynchronously via InvokeLater.
+ void ResponseStarted();
+ int ReadCompleted(void* buf, uint32 buf_size);
+
+ enum ReadyStates {
+ READY_INVALID = 0,
+ READY_WAITING = 1,
+ READY_GOT_HEADERS = 2,
+ READY_GOT_DATA = 3,
+ };
+ const TestResponsePayload* payload_;
+ uint32 offset_;
+ int ready_state_;
+ CPRequest* request_;
+};
+
+ResponseStream::ResponseStream(const TestResponsePayload* payload,
+ CPRequest* request)
+ : payload_(payload), offset_(0), request_(request),
+ ready_state_(READY_INVALID) {
+}
+
+void ResponseStream::Init() {
+ if (payload_->async) {
+ // simulate an asynchronous start complete
+ ready_state_ = READY_WAITING;
+ g_cptest_funcs.invoke_later(
+ InvokeLaterCallback,
+ // downcast to Task before void, since we upcast from void to Task.
+ static_cast<Task*>(
+ NewRunnableMethod(this, &ResponseStream::ResponseStarted)),
+ 500);
+ } else {
+ ready_state_ = READY_GOT_DATA;
+ }
+}
+
+int ResponseStream::GetResponseInfo(CPResponseInfoType type, void* buf,
+ uint32 buf_size) {
+ if (ready_state_ < READY_GOT_HEADERS)
+ return CPERR_FAILURE;
+
+ switch (type) {
+ case CPRESPONSEINFO_HTTP_STATUS:
+ if (buf) {
+ int status = payload_->status;
+ memcpy(buf, &payload_->status, buf_size);
+ }
+ break;
+ case CPRESPONSEINFO_HTTP_RAW_HEADERS: {
+ std::string headers = GetPayloadHeaders(payload_);
+ if (buf_size < headers.size()+1)
+ return static_cast<int>(headers.size()+1);
+ if (buf)
+ memcpy(buf, headers.c_str(), headers.size()+1);
+ break;
+ }
+ default:
+ return CPERR_INVALID_VERSION;
+ }
+
+ return CPERR_SUCCESS;
+}
+
+int ResponseStream::ReadData(void* buf, uint32 buf_size) {
+ if (ready_state_ < READY_GOT_DATA) {
+ // simulate an asynchronous read complete
+ g_cptest_funcs.invoke_later(
+ InvokeLaterCallback,
+ // downcast to Task before void, since we upcast from void to Task.
+ static_cast<Task*>(
+ NewRunnableMethod(this, &ResponseStream::ReadCompleted,
+ buf, buf_size)),
+ 500);
+ return CPERR_IO_PENDING;
+ }
+
+ // synchronously complete the read
+ return ReadCompleted(buf, buf_size);
+}
+
+void ResponseStream::ResponseStarted() {
+ ready_state_ = READY_GOT_HEADERS;
+ g_cpresponse_funcs.start_completed(request_, CPERR_SUCCESS);
+}
+
+int ResponseStream::ReadCompleted(void* buf, uint32 buf_size) {
+ uint32 size = static_cast<uint32>(strlen(payload_->body));
+ uint32 avail = size - offset_;
+ uint32 count = buf_size;
+ if (count > avail)
+ count = avail;
+
+ if (count) {
+ memcpy(buf, payload_->body + offset_, count);
+ }
+
+ offset_ += count;
+
+ if (ready_state_ < READY_GOT_DATA) {
+ ready_state_ = READY_GOT_DATA;
+ g_cpresponse_funcs.read_completed(request_, static_cast<int>(count));
+ }
+
+ return count;
+}
+
+// CPP Funcs
+
+CPError STDCALL CPP_Shutdown() {
+ return CPERR_SUCCESS;
+}
+
+CPBool STDCALL CPP_ShouldInterceptRequest(CPRequest* request) {
+ DCHECK(StrNCaseCmp(request->url, kChromeTestPluginProtocol,
+ arraysize(kChromeTestPluginProtocol) - 1) == 0);
+ return FindPayload(request->url) != NULL;
+}
+
+CPError STDCALL CPR_StartRequest(CPRequest* request) {
+ const TestResponsePayload* payload = FindPayload(request->url);
+ DCHECK(payload);
+ ResponseStream* stream = new ResponseStream(payload, request);
+ stream->AddRef(); // Released in CPR_EndRequest
+ stream->Init();
+ request->pdata = stream;
+ return payload->async ? CPERR_IO_PENDING : CPERR_SUCCESS;
+}
+
+void STDCALL CPR_EndRequest(CPRequest* request, CPError reason) {
+ ResponseStream* stream = static_cast<ResponseStream*>(request->pdata);
+ request->pdata = NULL;
+ stream->Release(); // balances AddRef in CPR_StartRequest
+}
+
+void STDCALL CPR_SetExtraRequestHeaders(CPRequest* request,
+ const char* headers) {
+ // doesn't affect us
+}
+
+void STDCALL CPR_SetRequestLoadFlags(CPRequest* request, uint32 flags) {
+ // doesn't affect us
+}
+
+void STDCALL CPR_AppendDataToUpload(CPRequest* request, const char* bytes,
+ int bytes_len) {
+ // doesn't affect us
+}
+
+CPError STDCALL CPR_AppendFileToUpload(CPRequest* request, const char* filepath,
+ uint64 offset, uint64 length) {
+ // doesn't affect us
+ return CPERR_FAILURE;
+}
+
+int STDCALL CPR_GetResponseInfo(CPRequest* request, CPResponseInfoType type,
+ void* buf, uint32 buf_size) {
+ ResponseStream* stream = static_cast<ResponseStream*>(request->pdata);
+ return stream->GetResponseInfo(type, buf, buf_size);
+}
+
+int STDCALL CPR_Read(CPRequest* request, void* buf, uint32 buf_size) {
+ ResponseStream* stream = static_cast<ResponseStream*>(request->pdata);
+ return stream->ReadData(buf, buf_size);
+}
+
+// RequestResponse: manages the retrieval of response data from the host
+
+class RequestResponse {
+public:
+ RequestResponse(const std::string& raw_headers)
+ : raw_headers_(raw_headers), offset_(0) {}
+ void StartReading(CPRequest* request);
+ void ReadCompleted(CPRequest* request, int bytes_read);
+
+private:
+ std::string raw_headers_;
+ std::string body_;
+ int offset_;
+};
+
+void RequestResponse::StartReading(CPRequest* request) {
+ int rv = 0;
+ const uint32 kReadSize = 4096;
+ do {
+ body_.resize(offset_ + kReadSize);
+ rv = g_cprequest_funcs.read(request, &body_[offset_], kReadSize);
+ if (rv > 0)
+ offset_ += rv;
+ } while (rv > 0);
+
+ if (rv != CPERR_IO_PENDING) {
+ // Either an error occurred, or we are done.
+ ReadCompleted(request, rv);
+ }
+}
+
+void RequestResponse::ReadCompleted(CPRequest* request, int bytes_read) {
+ if (bytes_read > 0) {
+ offset_ += bytes_read;
+ StartReading(request);
+ return;
+ }
+
+ body_.resize(offset_);
+ bool success = (bytes_read == 0);
+ g_cptest_funcs.test_complete(request, success, raw_headers_, body_);
+ g_cprequest_funcs.end_request(request, CPERR_CANCELLED);
+ delete this;
+}
+
+void STDCALL CPRR_ReceivedRedirect(CPRequest* request, const char* new_url) {
+}
+
+void STDCALL CPRR_StartCompleted(CPRequest* request, CPError result) {
+ DCHECK(!request->pdata);
+
+ std::string raw_headers;
+ int size = g_cprequest_funcs.get_response_info(
+ request, CPRESPONSEINFO_HTTP_RAW_HEADERS, NULL, 0);
+ int rv = size < 0 ? size : g_cprequest_funcs.get_response_info(
+ request, CPRESPONSEINFO_HTTP_RAW_HEADERS,
+ WriteInto(&raw_headers, size+1), size);
+ if (rv != CPERR_SUCCESS) {
+ g_cptest_funcs.test_complete(request, false, std::string(), std::string());
+ g_cprequest_funcs.end_request(request, CPERR_CANCELLED);
+ return;
+ }
+
+ RequestResponse* response = new RequestResponse(raw_headers);
+ request->pdata = response;
+ response->StartReading(request);
+}
+
+void STDCALL CPRR_ReadCompleted(CPRequest* request, int bytes_read) {
+ RequestResponse* response =
+ reinterpret_cast<RequestResponse*>(request->pdata);
+ response->ReadCompleted(request, bytes_read);
+}
+
+int STDCALL CPT_MakeRequest(const char* method, const GURL& url) {
+ CPRequest* request = NULL;
+ if (g_cpbrowser_funcs.create_request(g_cpid, NULL, method, url.spec().c_str(),
+ &request) != CPERR_SUCCESS ||
+ !request) {
+ return CPERR_FAILURE;
+ }
+
+ g_cprequest_funcs.set_request_load_flags(request,
+ CPREQUESTLOAD_DISABLE_INTERCEPT);
+
+ if (strcmp(method, "POST") == 0) {
+ g_cprequest_funcs.set_extra_request_headers(
+ request, "Content-Type: text/plain");
+ g_cprequest_funcs.append_data_to_upload(
+ request, kChromeTestPluginPostData,
+ arraysize(kChromeTestPluginPostData) - 1);
+ }
+
+ int rv = g_cprequest_funcs.start_request(request);
+ if (rv == CPERR_SUCCESS) {
+ CPRR_StartCompleted(request, CPERR_SUCCESS);
+ } else if (rv != CPERR_IO_PENDING) {
+ g_cprequest_funcs.end_request(request, CPERR_CANCELLED);
+ return CPERR_FAILURE;
+ }
+
+ return CPERR_SUCCESS;
+}
+
+// DLL entry points
+
+CPError STDCALL CP_Initialize(CPID id, const CPBrowserFuncs* bfuncs,
+ CPPluginFuncs* pfuncs) {
+ if (bfuncs == NULL || pfuncs == NULL)
+ return CPERR_FAILURE;
+
+ if (CP_GET_MAJOR_VERSION(bfuncs->version) > CP_MAJOR_VERSION)
+ return CPERR_INVALID_VERSION;
+
+ if (bfuncs->size < sizeof(CPBrowserFuncs) ||
+ pfuncs->size < sizeof(CPPluginFuncs))
+ return CPERR_INVALID_VERSION;
+
+ pfuncs->version = CP_VERSION;
+ pfuncs->shutdown = CPP_Shutdown;
+ pfuncs->should_intercept_request = CPP_ShouldInterceptRequest;
+
+ static CPRequestFuncs request_funcs;
+ request_funcs.start_request = CPR_StartRequest;
+ request_funcs.end_request = CPR_EndRequest;
+ request_funcs.set_extra_request_headers = CPR_SetExtraRequestHeaders;
+ request_funcs.set_request_load_flags = CPR_SetRequestLoadFlags;
+ request_funcs.append_data_to_upload = CPR_AppendDataToUpload;
+ request_funcs.get_response_info = CPR_GetResponseInfo;
+ request_funcs.read = CPR_Read;
+ request_funcs.append_file_to_upload = CPR_AppendFileToUpload;
+ pfuncs->request_funcs = &request_funcs;
+
+ static CPResponseFuncs response_funcs;
+ response_funcs.received_redirect = CPRR_ReceivedRedirect;
+ response_funcs.start_completed = CPRR_StartCompleted;
+ response_funcs.read_completed = CPRR_ReadCompleted;
+ pfuncs->response_funcs = &response_funcs;
+
+ g_cpid = id;
+ g_cpbrowser_funcs = *bfuncs;
+ g_cprequest_funcs = *bfuncs->request_funcs;
+ g_cpresponse_funcs = *bfuncs->response_funcs;
+ g_cpbrowser_funcs = *bfuncs;
+
+ const char* protocols[] = {kChromeTestPluginProtocol};
+ g_cpbrowser_funcs.enable_request_intercept(g_cpid, protocols, 1);
+ return CPERR_SUCCESS;
+}
+
+int STDCALL CP_Test(void* vparam) {
+ TestFuncParams* param = reinterpret_cast<TestFuncParams*>(vparam);
+ param->pfuncs.test_make_request = CPT_MakeRequest;
+
+ g_cptest_funcs = param->bfuncs;
+ return CPERR_SUCCESS;
+}
diff --git a/chrome/test/chrome_plugin/test_chrome_plugin.def b/chrome/test/chrome_plugin/test_chrome_plugin.def
new file mode 100644
index 0000000..18a26cb
--- /dev/null
+++ b/chrome/test/chrome_plugin/test_chrome_plugin.def
@@ -0,0 +1,4 @@
+EXPORTS
+ CP_Initialize @1
+ CP_Test @2
+
diff --git a/chrome/test/chrome_plugin/test_chrome_plugin.h b/chrome/test/chrome_plugin/test_chrome_plugin.h
new file mode 100644
index 0000000..3f3f1c5
--- /dev/null
+++ b/chrome/test/chrome_plugin/test_chrome_plugin.h
@@ -0,0 +1,92 @@
+// 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.
+// Shared by the plugin DLL and the unittest code.
+
+#ifndef CHROME_TEST_CHROME_PLUGIN_TEST_CHROME_PLUGIN_H__
+#define CHROME_TEST_CHROME_PLUGIN_TEST_CHROME_PLUGIN_H__
+
+#include "base/basictypes.h"
+#include "chrome/common/chrome_plugin_api.h"
+#include "googleurl/src/gurl.h"
+
+struct TestResponsePayload {
+ const char* url;
+ bool async;
+ int status;
+ const char* mime_type;
+ const char* body;
+};
+
+const char kChromeTestPluginProtocol[] = "cptest";
+
+const TestResponsePayload kChromeTestPluginPayloads[] = {
+ {
+ "cptest:sync",
+ false,
+ 200,
+ "text/html",
+ "<head><title>cptest:sync</title></head><body>SUCCESS</body>"
+ },
+ {
+ "cptest:async",
+ true,
+ 200,
+ "text/plain",
+ "<head><title>cptest:async</title></head><body>SUCCESS</body>"
+ },
+ {
+ "cptest:blank",
+ false,
+ 200,
+ "text/plain",
+ ""
+ },
+};
+
+struct TestFuncParams {
+ typedef void (STDCALL *CallbackFunc)(void* data);
+
+ struct PluginFuncs {
+ int (STDCALL *test_make_request)(const char* method, const GURL& url);
+ };
+ PluginFuncs pfuncs;
+
+ struct BrowserFuncs {
+ void (STDCALL *test_complete)(CPRequest* request, bool success,
+ const std::string& raw_headers,
+ const std::string& body);
+ void (STDCALL *invoke_later)(CallbackFunc callback, void* callback_data,
+ int delay_ms);
+ };
+ BrowserFuncs bfuncs;
+};
+
+const char kChromeTestPluginPostData[] = "Test Data";
+
+#endif // CHROME_TEST_CHROME_PLUGIN_TEST_CHROME_PLUGIN_H__
diff --git a/chrome/test/chrome_plugin/test_chrome_plugin.vcproj b/chrome/test/chrome_plugin/test_chrome_plugin.vcproj
new file mode 100644
index 0000000..243c494
--- /dev/null
+++ b/chrome/test/chrome_plugin/test_chrome_plugin.vcproj
@@ -0,0 +1,159 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="test_chrome_plugin"
+ ProjectGUID="{7F0A70F6-BE3F-4C19-B435-956AB8F30BA4}"
+ RootNamespace="startup_tests"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ ConfigurationType="2"
+ InheritedPropertySheets="$(SolutionDir)..\build\debug.vsprops;.\test_chrome_plugin.vsprops"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="0"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="winmm.lib"
+ />
+ <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"
+ ConfigurationType="2"
+ InheritedPropertySheets="$(SolutionDir)..\build\release.vsprops;.\test_chrome_plugin.vsprops"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="winmm.lib"
+ />
+ <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>
+ <File
+ RelativePath=".\test_chrome_plugin.cc"
+ >
+ </File>
+ <File
+ RelativePath=".\test_chrome_plugin.def"
+ >
+ </File>
+ <File
+ RelativePath=".\test_chrome_plugin.h"
+ >
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/chrome/test/chrome_plugin/test_chrome_plugin.vsprops b/chrome/test/chrome_plugin/test_chrome_plugin.vsprops
new file mode 100644
index 0000000..d3d0829
--- /dev/null
+++ b/chrome/test/chrome_plugin/test_chrome_plugin.vsprops
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioPropertySheet
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="test_chrome_plugin"
+ InheritedPropertySheets="$(SolutionDir)..\build\common.vsprops"
+ >
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="winmm.lib"
+ ModuleDefinitionFile="test_chrome_plugin.def"
+ />
+</VisualStudioPropertySheet>
diff --git a/chrome/test/data/animate1.gif b/chrome/test/data/animate1.gif
new file mode 100644
index 0000000..2de64b0
--- /dev/null
+++ b/chrome/test/data/animate1.gif
Binary files differ
diff --git a/chrome/test/data/animate2.gif b/chrome/test/data/animate2.gif
new file mode 100644
index 0000000..2a4233d
--- /dev/null
+++ b/chrome/test/data/animate2.gif
Binary files differ
diff --git a/chrome/test/data/animate3.gif b/chrome/test/data/animate3.gif
new file mode 100644
index 0000000..21f9c05
--- /dev/null
+++ b/chrome/test/data/animate3.gif
Binary files differ
diff --git a/chrome/test/data/animated-gifs.html b/chrome/test/data/animated-gifs.html
new file mode 100644
index 0000000..98b2f1c
--- /dev/null
+++ b/chrome/test/data/animated-gifs.html
@@ -0,0 +1,8 @@
+<html>
+<head><title>animated gif test</title></head>
+<body>
+<img src="animate1.gif">
+<img src="animate2.gif">
+<img src="animate3.gif">
+</body>
+</html>
diff --git a/chrome/test/data/cancelled_redirect_test.html b/chrome/test/data/cancelled_redirect_test.html
new file mode 100644
index 0000000..633db40
--- /dev/null
+++ b/chrome/test/data/cancelled_redirect_test.html
@@ -0,0 +1,28 @@
+<!--Test file for ClientCancelled redirect_uitest. This tests that a location change when a pending
+client redirect exists (in this case a meta-refresh) isn't flagged as a client redirect. The timeout
+for the meta-refresh is large so that it can't happen during this test; we just want it to be scheduled.
+We can't use a body onload to do the location change, because this will end up firing before the
+meta-refresh timer is scheduled, so we use a non-zero timeout of 1msec for this. -->
+<html>
+ <head>
+ <meta http-equiv="refresh" content="20000">
+ <script>
+ // Function to simulate a user clicking on the button, so
+ // the anchor navigation is not flagged as a redirect.
+ function clickButton() {
+ var node = document.getElementById("mybutton");
+ var evt = document.createEvent("MouseEvents");
+ evt.initMouseEvent("click", true, true, window, 0, 0, 0, 0, 0,
+ false, false, false, false, 0, null);
+ node.dispatchEvent(evt)
+ }
+ function changeLocAfterTimeout() {
+ setTimeout("clickButton()", 1);
+ }
+ </script>
+ </head>
+ <body onload="changeLocAfterTimeout()">
+ <input type="button" id="mybutton" onclick="document.location='#myanchor'"/>
+ <a name="myanchor">Anchor</a><br/>
+ </body>
+</html>
diff --git a/chrome/test/data/columns.html b/chrome/test/data/columns.html
new file mode 100644
index 0000000..84b688d
--- /dev/null
+++ b/chrome/test/data/columns.html
@@ -0,0 +1,23 @@
+<html><head><title>Column test</title></head><body>
+<h1>Column test</h1>
+
+<p>This tests that we do multi-column layout and don't crash. The issue is
+that WebKit creates a NULL platform graphics context pointer, and expects
+GraphicsContext to work with it, disabling paint.</p>
+
+<div style="border: 2px solid rgb(34, 136, 17); -webkit-column-count: 2;
+-moz-column-count: 2; -webkit-column-rule: 2px solid rgb(34, 136, 17);
+-moz-column-rule: 4px solid rgb(34, 136, 17)">WebKit now has some very basic
+support for multiple columns from CSS3. In fact, if you&#8217;re reading this
+blog entry, you will see that it has been broken up into two columns in the
+latest WebKit nightly and in Firefox.<br />
+
+<div style="margin: 1em 0">The properties supported at this time are columns,
+column-gap, column-count and column-width. Column rules are not yet supported
+and neither are column breaks.</div> At this time any stacking context children
+like relative positioned content or content that uses opacity will position
+impoperly (as though the column didn&#8217;t exist. If you decide to use this
+feature, watch out for that.<br /> <div style="margin-top:1em"><b>Update</b>:
+Column rules are now supported. This blog entry now has one!</div>
+
+</body></html>
diff --git a/chrome/test/data/constrained_files/constrained_window.html b/chrome/test/data/constrained_files/constrained_window.html
new file mode 100644
index 0000000..1f4810a
--- /dev/null
+++ b/chrome/test/data/constrained_files/constrained_window.html
@@ -0,0 +1,17 @@
+<HTML>
+ <HEAD>
+ <TITLE>
+ Parent Window
+ </TITLE>
+<SCRIPT TYPE="text/javascript" LANGUAGE="JavaScript">
+<!-- Begin
+function enter(url, x, y) {
+ window.open(url,'','height=320,width=300,left='+x+',top='+y);
+}
+// End -->
+</SCRIPT>
+
+ <BODY
+ onload="enter('target0.html', 10, 10); enter('target1.html', 100, 100)">
+ </BODY>
+ </HTML>
diff --git a/chrome/test/data/constrained_files/constrained_window_onload_moveto.html b/chrome/test/data/constrained_files/constrained_window_onload_moveto.html
new file mode 100644
index 0000000..9da3aa6
--- /dev/null
+++ b/chrome/test/data/constrained_files/constrained_window_onload_moveto.html
@@ -0,0 +1,17 @@
+<HTML>
+ <HEAD>
+ <TITLE>
+ Parent Window
+ </TITLE>
+<SCRIPT TYPE="text/javascript" LANGUAGE="JavaScript">
+<!-- Begin
+function enter(url, x, y) {
+ window.open(url,'','height=320,width=300,left='+x+',top='+y);
+}
+// End -->
+</SCRIPT>
+
+ <BODY
+ onload="enter('target_onload_moveto.html', 100, 100);">
+ </BODY>
+ </HTML>
diff --git a/chrome/test/data/constrained_files/constrained_window_onload_resizeto.html b/chrome/test/data/constrained_files/constrained_window_onload_resizeto.html
new file mode 100644
index 0000000..e1990f3
--- /dev/null
+++ b/chrome/test/data/constrained_files/constrained_window_onload_resizeto.html
@@ -0,0 +1,17 @@
+<HTML>
+ <HEAD>
+ <TITLE>
+ Parent Window
+ </TITLE>
+<SCRIPT TYPE="text/javascript" LANGUAGE="JavaScript">
+<!-- Begin
+function enter(url, x, y) {
+ window.open(url,'','height=320,width=300,left='+x+',top='+y);
+}
+// End -->
+</SCRIPT>
+
+ <BODY onClick="enter('target_onload_resizeto.html', 100, 100);">
+
+ </BODY>
+</HTML>
diff --git a/chrome/test/data/constrained_files/target0.html b/chrome/test/data/constrained_files/target0.html
new file mode 100644
index 0000000..8185d9d
--- /dev/null
+++ b/chrome/test/data/constrained_files/target0.html
@@ -0,0 +1,8 @@
+<HTML>
+ <HEAD>
+ <TITLE> Constrained Window 0 </TITLE>
+ </HEAD>
+ <BODY>
+ This page should be used to pop up a constrained window.
+ </BODY>
+</HTML>
diff --git a/chrome/test/data/constrained_files/target1.html b/chrome/test/data/constrained_files/target1.html
new file mode 100644
index 0000000..d4c2dba
--- /dev/null
+++ b/chrome/test/data/constrained_files/target1.html
@@ -0,0 +1,6 @@
+
+<HTML>
+ <HEAD>
+ <TITLE> Constrained Window 1 </TITLE>
+ </HEAD>
+</HTML>
diff --git a/chrome/test/data/constrained_files/target_onload_moveto.html b/chrome/test/data/constrained_files/target_onload_moveto.html
new file mode 100644
index 0000000..02ade91
--- /dev/null
+++ b/chrome/test/data/constrained_files/target_onload_moveto.html
@@ -0,0 +1,8 @@
+<HTML>
+ <HEAD>
+ <TITLE> window.moveTo() Test </TITLE>
+ </HEAD>
+ <BODY onLoad="window.opener.focus(); window.moveTo(20, 20);">
+ This page shouldn't be able to force its own display by moving itself after creation.
+ </BODY>
+</HTML>
diff --git a/chrome/test/data/constrained_files/target_onload_resizeto.html b/chrome/test/data/constrained_files/target_onload_resizeto.html
new file mode 100644
index 0000000..e19f144
--- /dev/null
+++ b/chrome/test/data/constrained_files/target_onload_resizeto.html
@@ -0,0 +1,9 @@
+<HTML>
+ <HEAD>
+ <TITLE> window.resizeTo() Test </TITLE>
+ </HEAD>
+ <BODY onClick="window.opener.focus(); window.resizeTo(200, 200);">
+ This page's content bounds should start at 320, 300 because that's hat it was opeend with.
+ After click, the window's bounds should be equal to 200, 200 and the content bounds smaller then that.
+ </BODY>
+</HTML>
diff --git a/chrome/test/data/content-disposition-empty.html b/chrome/test/data/content-disposition-empty.html
new file mode 100644
index 0000000..7dd9c0f
--- /dev/null
+++ b/chrome/test/data/content-disposition-empty.html
@@ -0,0 +1,4 @@
+<html>
+<head><title>success</title></head>
+<body>this page should be displayed instead of downloaded</body>
+</html>
diff --git a/chrome/test/data/content-disposition-empty.html.mock-http-headers b/chrome/test/data/content-disposition-empty.html.mock-http-headers
new file mode 100644
index 0000000..1d114d5
--- /dev/null
+++ b/chrome/test/data/content-disposition-empty.html.mock-http-headers
@@ -0,0 +1,6 @@
+HTTP/1.1 200 OK
+Content-Type: text/html
+Content-Length: 116
+Content-Disposition: filename="foo.html"
+Date: Mon, 13 Nov 2006 21:38:09 GMT
+Expires: Tue, 14 Nov 2006 19:23:58 GMT
diff --git a/chrome/test/data/content-disposition-inline.html b/chrome/test/data/content-disposition-inline.html
new file mode 100644
index 0000000..7dd9c0f
--- /dev/null
+++ b/chrome/test/data/content-disposition-inline.html
@@ -0,0 +1,4 @@
+<html>
+<head><title>success</title></head>
+<body>this page should be displayed instead of downloaded</body>
+</html>
diff --git a/chrome/test/data/content-disposition-inline.html.mock-http-headers b/chrome/test/data/content-disposition-inline.html.mock-http-headers
new file mode 100644
index 0000000..6846a51
--- /dev/null
+++ b/chrome/test/data/content-disposition-inline.html.mock-http-headers
@@ -0,0 +1,6 @@
+HTTP/1.1 200 OK
+Content-Type: text/html
+Content-Length: 116
+Content-Disposition: inline; filename="foo.html"
+Date: Mon, 13 Nov 2006 21:38:09 GMT
+Expires: Tue, 14 Nov 2006 19:23:58 GMT
diff --git a/chrome/test/data/content-sniffer-test0.html b/chrome/test/data/content-sniffer-test0.html
new file mode 100644
index 0000000..597a51b
--- /dev/null
+++ b/chrome/test/data/content-sniffer-test0.html
@@ -0,0 +1,4 @@
+<html>
+<head><title>Content Sniffer Test 0</title></head>
+<body>We should sniff this content as HTML.</body>
+</html>
diff --git a/chrome/test/data/content-sniffer-test0.html.mock-http-headers b/chrome/test/data/content-sniffer-test0.html.mock-http-headers
new file mode 100644
index 0000000..0e1e649
--- /dev/null
+++ b/chrome/test/data/content-sniffer-test0.html.mock-http-headers
@@ -0,0 +1,4 @@
+HTTP/1.1 200 OK
+Content-Length: 121
+Date: Mon, 13 Nov 2006 21:38:09 GMT
+Expires: Tue, 14 Nov 2006 19:23:58 GMT
diff --git a/chrome/test/data/content-sniffer-test1.html b/chrome/test/data/content-sniffer-test1.html
new file mode 100644
index 0000000..c3bfc9b
--- /dev/null
+++ b/chrome/test/data/content-sniffer-test1.html
@@ -0,0 +1,4 @@
+<html>
+<head><title>Content Sniffer Test 1</title></head>
+<body>We should not sniff this content as HTML.</body>
+</html>
diff --git a/chrome/test/data/content-sniffer-test1.html.mock-http-headers b/chrome/test/data/content-sniffer-test1.html.mock-http-headers
new file mode 100644
index 0000000..bbc82cdf
--- /dev/null
+++ b/chrome/test/data/content-sniffer-test1.html.mock-http-headers
@@ -0,0 +1,5 @@
+HTTP/1.1 200 OK
+Content-Type: text/plain; charset=utf-8
+Content-Length: 125
+Date: Mon, 13 Nov 2006 21:38:09 GMT
+Expires: Tue, 14 Nov 2006 19:23:58 GMT
diff --git a/chrome/test/data/content-sniffer-test2.html b/chrome/test/data/content-sniffer-test2.html
new file mode 100644
index 0000000..c4b99f8
--- /dev/null
+++ b/chrome/test/data/content-sniffer-test2.html
@@ -0,0 +1,4 @@
+<html>
+<head><title>Content Sniffer Test 2</title></head>
+<body>We should not sniff this as HTML as server says its a GIF.</body>
+</html>
diff --git a/chrome/test/data/content-sniffer-test2.html.mock-http-headers b/chrome/test/data/content-sniffer-test2.html.mock-http-headers
new file mode 100644
index 0000000..081626d
--- /dev/null
+++ b/chrome/test/data/content-sniffer-test2.html.mock-http-headers
@@ -0,0 +1,5 @@
+HTTP/1.1 200 OK
+Content-Type: image/gif
+Content-Length: 142
+Date: Mon, 13 Nov 2006 21:38:09 GMT
+Expires: Tue, 14 Nov 2006 19:23:58 GMT
diff --git a/chrome/test/data/content-sniffer-test3-frame.txt b/chrome/test/data/content-sniffer-test3-frame.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/chrome/test/data/content-sniffer-test3-frame.txt
diff --git a/chrome/test/data/content-sniffer-test3-frame.txt.mock-http-headers b/chrome/test/data/content-sniffer-test3-frame.txt.mock-http-headers
new file mode 100644
index 0000000..7ad4001
--- /dev/null
+++ b/chrome/test/data/content-sniffer-test3-frame.txt.mock-http-headers
@@ -0,0 +1,3 @@
+HTTP/1.1 200 OK
+Content-Length: 0
+Date: Tue, 22 Apr 2008 22:56:55 GMT
diff --git a/chrome/test/data/content-sniffer-test3.html b/chrome/test/data/content-sniffer-test3.html
new file mode 100644
index 0000000..67046e8
--- /dev/null
+++ b/chrome/test/data/content-sniffer-test3.html
@@ -0,0 +1,16 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<meta HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=UTF-8">
+<title>Content Sniffer Test 3</title>
+</head>
+<body>
+<script id="sc">
+var iframe = document.createElement('iframe');
+iframe.frameBorder = iframe.width = iframe.height = 0;
+iframe.src = "http://mock.http/content-sniffer-test3-frame.txt";
+document.body.appendChild(iframe);
+</script>
+<pre>Do NOT download!!</pre>
+</body>
+</html> \ No newline at end of file
diff --git a/chrome/test/data/content-sniffer-test3.html.mock-http-headers b/chrome/test/data/content-sniffer-test3.html.mock-http-headers
new file mode 100644
index 0000000..a2e08d5
--- /dev/null
+++ b/chrome/test/data/content-sniffer-test3.html.mock-http-headers
@@ -0,0 +1,5 @@
+HTTP/1.1 200 OK
+Content-Length: 487
+Date: Tue, 22 Apr 2008 22:56:55 GMT
+Content-Length: 333
+Content-Type: text/html
diff --git a/chrome/test/data/cookie1.html b/chrome/test/data/cookie1.html
new file mode 100644
index 0000000..3c7dccf
--- /dev/null
+++ b/chrome/test/data/cookie1.html
@@ -0,0 +1,11 @@
+<html>
+<head>
+<script>
+function setCookie() {
+ document.cookie = 'foo=baz';
+}
+</script>
+</head>
+<body onload="setCookie();">
+</body>
+</html>
diff --git a/chrome/test/data/download-test1.lib b/chrome/test/data/download-test1.lib
new file mode 100644
index 0000000..9d22027
--- /dev/null
+++ b/chrome/test/data/download-test1.lib
Binary files differ
diff --git a/chrome/test/data/download-test1.lib.mock-http-headers b/chrome/test/data/download-test1.lib.mock-http-headers
new file mode 100644
index 0000000..63aef68
--- /dev/null
+++ b/chrome/test/data/download-test1.lib.mock-http-headers
@@ -0,0 +1,5 @@
+HTTP/1.1 200 OK
+Content-Type: application/octet-stream; charset=utf-8
+Content-Length: 271920
+Date: Mon, 13 Nov 2006 21:38:09 GMT
+Expires: Tue, 14 Nov 2006 19:23:58 GMT
diff --git a/chrome/test/data/download-test2.html b/chrome/test/data/download-test2.html
new file mode 100644
index 0000000..1a6714e
--- /dev/null
+++ b/chrome/test/data/download-test2.html
@@ -0,0 +1,4 @@
+<html>
+<head><title>Download Test #2</title></head>
+<body>This file should not actually download.</body>
+</html>
diff --git a/chrome/test/data/download-test2.html.mock-http-headers b/chrome/test/data/download-test2.html.mock-http-headers
new file mode 100644
index 0000000..fa7ff58
--- /dev/null
+++ b/chrome/test/data/download-test2.html.mock-http-headers
@@ -0,0 +1,5 @@
+HTTP/1.1 200 OK
+Content-Type: text/html; charset=utf-8
+Content-Length: 113
+Date: Mon, 13 Nov 2006 21:38:09 GMT
+Expires: Tue, 14 Nov 2006 19:23:58 GMT
diff --git a/chrome/test/data/download-test3.html b/chrome/test/data/download-test3.html
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/chrome/test/data/download-test3.html
diff --git a/chrome/test/data/download-test3.html.mock-http-headers b/chrome/test/data/download-test3.html.mock-http-headers
new file mode 100644
index 0000000..3a2e781
--- /dev/null
+++ b/chrome/test/data/download-test3.html.mock-http-headers
@@ -0,0 +1,6 @@
+HTTP/1.1 200 OK
+Content-Type: text/html; charset=utf-8
+Content-Disposition: attachment; filename="download-test3-attachment.html"
+Content-Length: 0
+Date: Mon, 13 Nov 2006 21:38:09 GMT
+Expires: Tue, 14 Nov 2006 19:23:58 GMT
diff --git a/chrome/test/data/empty.html b/chrome/test/data/empty.html
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/chrome/test/data/empty.html
diff --git a/chrome/test/data/file_client_redirect.html b/chrome/test/data/file_client_redirect.html
new file mode 100644
index 0000000..61dc261
--- /dev/null
+++ b/chrome/test/data/file_client_redirect.html
@@ -0,0 +1,8 @@
+<!--
+Test file for empty referrer client redirects, e.g https>http, file>http.
+See ClientEmptyReferrerRedirectTest in redirect_uitest.cc
+-->
+<html>
+<head></head>
+<body onload="document.location='http://localhost:1337'"></body>
+</html>
diff --git a/chrome/test/data/find_in_page/framedata_general.html b/chrome/test/data/find_in_page/framedata_general.html
new file mode 100644
index 0000000..8e8a82d
--- /dev/null
+++ b/chrome/test/data/find_in_page/framedata_general.html
@@ -0,0 +1,13 @@
+<html>
+<head>
+<title>Frames</title>
+</head>
+
+<body>
+
+horse <br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
+goat<br>
+goat<br><br><br><br><br><br><br><br><br><br><br><br><br><br>
+<input type="text"/>
+</body>
+</html> \ No newline at end of file
diff --git a/chrome/test/data/find_in_page/framedata_left.html b/chrome/test/data/find_in_page/framedata_left.html
new file mode 100644
index 0000000..794c6cf
--- /dev/null
+++ b/chrome/test/data/find_in_page/framedata_left.html
@@ -0,0 +1,21 @@
+<html>
+<head>
+<title>Frames</title>
+</head>
+
+<body>
+
+cat <br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
+dog <br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
+<input type="text" value="text in box"><br>
+
+g <br>
+go <br>
+goo <br>
+google <br>
+goog <br>
+googl <br>
+<br>
+Hreggvi&eth;ur
+</body>
+</html> \ No newline at end of file
diff --git a/chrome/test/data/find_in_page/frames.html b/chrome/test/data/find_in_page/frames.html
new file mode 100644
index 0000000..f89c6e5
--- /dev/null
+++ b/chrome/test/data/find_in_page/frames.html
@@ -0,0 +1,12 @@
+<html>
+
+<frameset cols="25%,25%,25%,25%">
+
+ <frame src="framedata_left.html">
+ <frame src="framedata_general.html">
+ <frame src="framedata_general.html">
+ <frame src="framedata_general.html">
+
+</frameset>
+
+</html>
diff --git a/chrome/test/data/find_in_page/user-select.html b/chrome/test/data/find_in_page/user-select.html
new file mode 100644
index 0000000..fccceb4
--- /dev/null
+++ b/chrome/test/data/find_in_page/user-select.html
@@ -0,0 +1,6 @@
+<html><head></head>
+<body style="-webkit-user-select: none;">
+This is some un-selectable text. Try finding a character in it
+and verify that we don't crash.
+</body>
+</html>
diff --git a/chrome/test/data/firefox2_nss/README b/chrome/test/data/firefox2_nss/README
new file mode 100644
index 0000000..745832e
--- /dev/null
+++ b/chrome/test/data/firefox2_nss/README
@@ -0,0 +1,7 @@
+The NSPR and NSS DLLs in this directory (freebl3.dll, nspr4.dll, nss3.dll,
+plc4.dll, plds4.dll, and softokn3.dll) come from the Firefox 2.0.0.x
+distribution for Windows.
+
+The source code of NSPR and NSS, which you may use, modify, and distribute, is
+available to you free-of-charge from www.mozilla.org under the Mozilla Public
+License and other open source software licenses.
diff --git a/chrome/test/data/firefox2_nss/freebl3.dll b/chrome/test/data/firefox2_nss/freebl3.dll
new file mode 100644
index 0000000..6e562d8
--- /dev/null
+++ b/chrome/test/data/firefox2_nss/freebl3.dll
Binary files differ
diff --git a/chrome/test/data/firefox2_nss/nspr4.dll b/chrome/test/data/firefox2_nss/nspr4.dll
new file mode 100644
index 0000000..5ff4cc5
--- /dev/null
+++ b/chrome/test/data/firefox2_nss/nspr4.dll
Binary files differ
diff --git a/chrome/test/data/firefox2_nss/nss3.dll b/chrome/test/data/firefox2_nss/nss3.dll
new file mode 100644
index 0000000..c7d0546
--- /dev/null
+++ b/chrome/test/data/firefox2_nss/nss3.dll
Binary files differ
diff --git a/chrome/test/data/firefox2_nss/plc4.dll b/chrome/test/data/firefox2_nss/plc4.dll
new file mode 100644
index 0000000..c4492c8
--- /dev/null
+++ b/chrome/test/data/firefox2_nss/plc4.dll
Binary files differ
diff --git a/chrome/test/data/firefox2_nss/plds4.dll b/chrome/test/data/firefox2_nss/plds4.dll
new file mode 100644
index 0000000..e10c683
--- /dev/null
+++ b/chrome/test/data/firefox2_nss/plds4.dll
Binary files differ
diff --git a/chrome/test/data/firefox2_nss/softokn3.dll b/chrome/test/data/firefox2_nss/softokn3.dll
new file mode 100644
index 0000000..159957c
--- /dev/null
+++ b/chrome/test/data/firefox2_nss/softokn3.dll
Binary files differ
diff --git a/chrome/test/data/firefox2_profile/bookmarks.html b/chrome/test/data/firefox2_profile/bookmarks.html
new file mode 100644
index 0000000..84020ad
--- /dev/null
+++ b/chrome/test/data/firefox2_profile/bookmarks.html
@@ -0,0 +1,37 @@
+<!DOCTYPE NETSCAPE-Bookmark-file-1>
+<!-- This is an automatically generated file.
+ It will be read and overwritten.
+ DO NOT EDIT! -->
+<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=UTF-8">
+<TITLE>Bookmarks</TITLE>
+<H1 LAST_MODIFIED="1206681701">Bookmarks</H1>
+
+<DL><p>
+ <DT><H3 LAST_MODIFIED="1206681655" PERSONAL_TOOLBAR_FOLDER="true" ID="rdf:#$FvPhC3">Bookmarks Toolbar Folder</H3>
+<DD>Add bookmarks to this folder to see them displayed on the Bookmarks Toolbar
+ <DL><p>
+ <DT><H3 ADD_DATE="1206681467" LAST_MODIFIED="1206681524" ID="rdf:#$F2zO.2">Folder</H3>
+<DD>This folder will be displayed on toolbar.
+ <DL><p>
+ <DT><A HREF="http://on.toolbar/bookmark/folder" ADD_DATE="1206681362" LAST_MODIFIED="1206681414" ID="rdf:#$E2zO.2">On Toolbar's Subfolder</A>
+ </DL><p>
+ <DT><A HREF="http://on.toolbar/bookmark" ADD_DATE="1206681362" LAST_MODIFIED="1206681414" ID="rdf:#$E2zO.2">On Bookmark Toolbar</A>
+ </DL><p>
+ <HR>
+ <DT><H3 ADD_DATE="1206681467" LAST_MODIFIED="1206681701" ID="rdf:#$H2zO.2">Folder</H3>
+ <DL><p>
+ <DT><A HREF="http://domain/" ADD_DATE="1206681681" LAST_MODIFIED="1206681699" ID="rdf:#$I2zO.2">New Bookmark</A>
+ </DL><p>
+ <DT><A HREF="http://domain.com/q?a=%22er%22&b=< >" ADD_DATE="1205904876" LAST_MODIFIED="1206681294" ID="rdf:#$3XrQI1">&lt;Name&gt;</A>
+ <DT><A HREF="http://www.google.com/" ADD_DATE="1206681298" LAST_MODIFIED="1206681734" SHORTCUTURL="google" WEB_PANEL="true" ID="rdf:#$D2zO.2">Google Home Page</A>
+<DD>Google Home Page
+ <DT><A HREF="http://chinese.site.cn/path?query=1#ref" ADD_DATE="1206681555" LAST_MODIFIED="1206681598" ID="rdf:#$G2zO.2">中文</A>
+ <DT><H3 ADD_DATE="1207558707" LAST_MODIFIED="1207558746" ID="rdf:#$guhL42">&lt; &gt; &amp; &quot; &#39; \ /</H3>
+<DD>&lt; &gt; &amp; &quot; &#39; \ /
+ <DL><p>
+ <DT><A HREF="http://g.cn/" ADD_DATE="1207558728" LAST_MODIFIED="1207558736" SHORTCUTURL="&lt; &gt; &amp; &quot; &#39; \ /" ID="rdf:#$huhL42">&lt; &gt; &amp; &quot; &#39; \ /</A>
+<DD>&lt; &gt; &amp; &quot; &#39; \ /
+ </DL><p>
+ <DT><A HREF="http://localhost:8080/test/hello.html" ADD_DATE="1212447159" LAST_VISIT="1212447251" LAST_MODIFIED="1212447248" SHORTCUTURL="post" ICON="data:" POST_DATA="lname%3D%25s" LAST_CHARSET="UTF-8" ID="rdf:#$weKaR3">Test Post keyword</A>
+ <DT><A HREF="mailto:username@host" ADD_DATE="1213257065" LAST_MODIFIED="1213257105" ID="rdf:#$U8bjH1">mail</A>
+</DL><p>
diff --git a/chrome/test/data/firefox2_profile/cert8.db b/chrome/test/data/firefox2_profile/cert8.db
new file mode 100644
index 0000000..ac40a33
--- /dev/null
+++ b/chrome/test/data/firefox2_profile/cert8.db
Binary files differ
diff --git a/chrome/test/data/firefox2_profile/cookies.txt b/chrome/test/data/firefox2_profile/cookies.txt
new file mode 100644
index 0000000..2a7249f
--- /dev/null
+++ b/chrome/test/data/firefox2_profile/cookies.txt
@@ -0,0 +1,10 @@
+# HTTP Cookie File
+# http://www.netscape.com/newsref/std/cookie_spec.html
+# This is a generated file! Do not edit.
+# To delete cookies, use the Cookie Manager.
+
+www.google.com FALSE /calendar/ FALSE 1237629519 S dasher_cpanel=sRewracv:calendar=_9TWj_US
+.domain TRUE /path/sub_path/ FALSE 1221083160 name value
+#HttpOnly_.en.site.com TRUE / FALSE 1269432000 KEY KEY=KEY
+.~~local~~ TRUE /C:/code-chrome-new/data/page_cycler/intl1/fc2.com/ FALSE 1490482342 cnt_7081_nv 1
+ FALSE /C:/Documents%20and%20Settings/filecookie/ FALSE 1211314466 AAA2 ZZZZZZZZZZZZ
diff --git a/chrome/test/data/firefox2_profile/history.dat b/chrome/test/data/firefox2_profile/history.dat
new file mode 100644
index 0000000..b2f6a83
--- /dev/null
+++ b/chrome/test/data/firefox2_profile/history.dat
@@ -0,0 +1,16 @@
+// <!-- <mdb:mork:z v="1.4"/> -->
+< <(a=c)> // (f=iso-8859-1)
+ (8A=Typed)(8B=LastPageVisited)(8C=ByteOrder)
+ (80=ns:history:db:row:scope:history:all)
+ (81=ns:history:db:table:kind:history)(82=URL)(83=Referrer)
+ (84=LastVisitDate)(85=FirstVisitDate)(86=VisitCount)(87=Name)
+ (88=Hostname)(89=Hidden)>
+
+<(80=LE)(81=http://en-us.www.mozilla.com/)
+ (82=1205364946314923)(83=en-us.www.mozilla.com)(84
+ =F$00i$00r$00e$00f$00o$00x$00 $00U$00p$00d$00a$00t$00e$00d$00)>
+{1:^80 {(k^81:c)(s=9)[1(^8C=LE)]}
+ [2(^82^81)(^84^82)(^85^82)(^88^83)(^87^84)]}
+
+@$${2{@
+@$$}2}@ \ No newline at end of file
diff --git a/chrome/test/data/firefox2_profile/key3.db b/chrome/test/data/firefox2_profile/key3.db
new file mode 100644
index 0000000..2e3b9f4
--- /dev/null
+++ b/chrome/test/data/firefox2_profile/key3.db
Binary files differ
diff --git a/chrome/test/data/firefox2_profile/prefs.js b/chrome/test/data/firefox2_profile/prefs.js
new file mode 100644
index 0000000..1ed35e3
--- /dev/null
+++ b/chrome/test/data/firefox2_profile/prefs.js
@@ -0,0 +1,209 @@
+# Mozilla User Preferences
+
+/* Do not edit this file.
+ *
+ * If you make changes to this file while the application is running,
+ * the changes will be overwritten when the application exits.
+ *
+ * To make a manual change to preferences, you can visit the URL about:config
+ * For more information, see http://www.mozilla.org/unix/customizing.html#prefs
+ */
+
+user_pref("accessibility.typeaheadfind.flashBar", 0);
+user_pref("app.update.lastUpdateTime.addon-background-update-timer", 1210196026);
+user_pref("app.update.lastUpdateTime.background-update-timer", 1210196626);
+user_pref("app.update.lastUpdateTime.blocklist-background-update-timer", 1210194826);
+user_pref("app.update.lastUpdateTime.microsummary-generator-update-timer", 1196114739);
+user_pref("app.update.lastUpdateTime.restart-nag-timer", 1208477359);
+user_pref("app.update.lastUpdateTime.search-engine-update-timer", 1210227671);
+user_pref("browser.download.dir", "C:\\Downloads");
+user_pref("browser.download.downloadDir", "C:\\Downloads");
+user_pref("browser.download.folderList", 2);
+user_pref("browser.download.lastDir", "C:\\Documents and Settings\\jcampan\\Desktop");
+user_pref("browser.download.manager.alertOnEXEOpen", true);
+user_pref("browser.download.manager.showWhenStarting", false);
+user_pref("browser.download.save_converter_index", 0);
+user_pref("browser.feeds.showFirstRunUI", false);
+user_pref("browser.history_expire_days.mirror", 9);
+user_pref("browser.migration.version", 1);
+user_pref("browser.places.createdDefaultQueries", true);
+user_pref("browser.places.createdSmartBookmarks", true);
+user_pref("browser.places.importBookmarksHTML", false);
+user_pref("browser.places.importDefaults", false);
+user_pref("browser.places.migratePostDataAnnotations", false);
+user_pref("browser.places.updateRecentTagsUri", false);
+user_pref("browser.preferences.advanced.selectedTabIndex", 0);
+user_pref("browser.preferences.privacy.selectedTabIndex", 0);
+user_pref("browser.search.defaultenginename", "Google");
+user_pref("browser.search.defaulturl", "http://www.google.com/search?lr=&ie=UTF-8&oe=UTF-8&q=");
+user_pref("browser.search.selectedEngine", "Webster");
+user_pref("browser.search.useDBForOrder", true);
+user_pref("browser.shell.checkDefaultBrowser", false);
+user_pref("browser.startup.homepage", "http://www.google.com/");
+user_pref("browser.startup.homepage_override.mstone", "rv:1.9b5");
+user_pref("browser.startup.page", 3);
+user_pref("extensions.adblockplus.checkedadblockinstalled", true);
+user_pref("extensions.adblockplus.checkedtoolbar", true);
+user_pref("extensions.adblockplus.showsubscriptions", false);
+user_pref("extensions.enabledItems", "{d10d0bf8-f5b5-c8b4-a8b2-2b9879e08c5d}:0.7.5.4,{77b819fa-95ad-4f2c-ac7c-486b356188a9}:1.5.20080310,{c45c406e-ab73-11d8-be73-000a95be3b12}:1.1.5,{972ce4c6-7e08-4474-a285-3208198ce6fd}:2.0");
+user_pref("extensions.lastAppVersion", "3.0b5");
+user_pref("extensions.piclens.InstanceId", "8A6zSIlUX0q0VBf/iJvL/Q==");
+user_pref("extensions.piclens.UpdateInfo", "H4sIAAAAAAAAC+1WwWoCMRT8m1wqZbVQ6GEPVtqTgtTFHmQPcTN1g9mk5GXd+vdNdkWqYi+lUkvY20xe3rzMDjxyxkLMHHc0hyVpdHrPqHmBFrCwgagpHTBdV2Ne66IEpQkjD09hpQmV1mWyQtq/HfSTwR1ukuSBOeO4mspiDE0tm4QbJkYgs1yTdL4RdeBQZGVdLUdKFusdNCu5xTMglrxYfyWeNF8qnBzdNdrjBG6D0sdttn1Hukh6B1/O8CGdZydwpRFHfM4Kox20G5Vcr3D+2EaiCawfasflzPlZj7GGKzUs2onP3HUsrzp8p5OqnKnWiw6mfSdSUmDeyeomX3zX6KyA3p+v8mX/dbKc8c1qFpwMwfmRkb2LyY6dfvZjxve7vFNt0MaGi5izmLPo1C/m7I1LBRGiFheTa15MCAqFg3j1G21cM6/dzSa6eP0ufgI#");
+user_pref("extensions.piclens.Version", "1.6.2.1605");
+user_pref("extensions.update.notifyUser", false);
+user_pref("google.toolbar.AUTOFILL_Preferences", "highlight\ntrue\nfullName\n\nemail\n\ndefaultPhone\n\nalternativePhone\n\naddressLine1\n\naddressLine2\n\naddressLine3\n\ncity\n\nstate\n\nzipcode\n\ncountry\n\ndefaultPhoneAll\n\nalternativePhoneAll\n\nworkPhoneAll\n\nhomePhoneAll\n\ncellPhoneAll\n\nfirstName\n\nmiddleName\n\nmiddleInit\n\nlastName\n\nfirstLastName\n\naddress\n\naddressFull\n\nzipshort\n\ndefaultPhoneWork\nfalse\nalternativePhoneWork\nfalse\ndefaultPhoneHome\nfalse\nalternativePhoneHome\nfalse\ndefaultPhoneCell\nfalse\nalternativePhoneCell\nfalse");
+user_pref("google.toolbar.auto_translate", false);
+user_pref("google.toolbar.button_option.gtbAutoFill", true);
+user_pref("google.toolbar.button_option.gtbAutoLink", true);
+user_pref("google.toolbar.button_option.gtbCustomButtonGmail", false);
+user_pref("google.toolbar.button_option.gtbSpellCheck", true);
+user_pref("google.toolbar.button_option.safebrowsing.advancedprotection.default", true);
+user_pref("google.toolbar.button_option.safebrowsing.hasrun", true);
+user_pref("google.toolbar.button_option.safebrowsing.tableversion.goog-sandbox-text", "1.5");
+user_pref("google.toolbar.button_option.safebrowsing.tableversion.goog-white-domain", "1.17");
+user_pref("google.toolbar.button_option.safebrowsing.tableversion.goog-white-url", "1.371");
+user_pref("google.toolbar.google_home", "www.google.com");
+user_pref("google.toolbar.install_id", "SnZA7ajGeiCa1tXwUT57CRjfrDqrmIzz46FGau14DDL9");
+user_pref("google.toolbar.install_ping_acked", true);
+user_pref("google.toolbar.install_ping_retires", 1);
+user_pref("google.toolbar.last_ping_attempt", "1160396718343");
+user_pref("google.toolbar.opted_into_advanced_features_1", true);
+user_pref("google.toolbar.rlz", "1B2GGGL_enIN176");
+user_pref("google.toolbar.search_box_history", "");
+user_pref("google.toolbar.search_box_use_suggest", true);
+user_pref("google.toolbar.sent", "1");
+user_pref("google.toolbar.spell_check.dictionary.words", "");
+user_pref("google.toolbar.spell_check.lang", "en");
+user_pref("google.toolbar.spell_check.last_lang", "en");
+user_pref("google.toolbar.subscribe.aggregators.LiveBookmarks.desc", "Read subscriptions with Firefox Live Bookmarks");
+user_pref("google.toolbar.subscribe.aggregators.LiveBookmarks.id", "LiveBookmarks");
+user_pref("google.toolbar.subscribe.aggregators.LiveBookmarks.order", "2");
+user_pref("google.toolbar.subscribe.aggregators.LiveBookmarks.title", "Firefox Live Bookmarks");
+user_pref("google.toolbar.subscribe.aggregators.LiveBookmarks.url", "LiveBookmarksUrl");
+user_pref("google.toolbar.subscribe.aggregators.bloglines.desc", "Personal page loaded with the freshest news about the things you love");
+user_pref("google.toolbar.subscribe.aggregators.bloglines.id", "bloglines");
+user_pref("google.toolbar.subscribe.aggregators.bloglines.order", "1");
+user_pref("google.toolbar.subscribe.aggregators.bloglines.title", "Bloglines");
+user_pref("google.toolbar.subscribe.aggregators.bloglines.url", "http://www.bloglines.com/sub/%feed%");
+user_pref("google.toolbar.subscribe.aggregators.iGoogle.desc", "Personalized Home");
+user_pref("google.toolbar.subscribe.aggregators.iGoogle.id", "iGoogle");
+user_pref("google.toolbar.subscribe.aggregators.iGoogle.order", "0");
+user_pref("google.toolbar.subscribe.aggregators.iGoogle.title", "Google personalized home");
+user_pref("google.toolbar.subscribe.aggregators.iGoogle.url", "http://fusion.google.com/add?feedurl=%feed%&client=firetools&hl=en");
+user_pref("google.toolbar.subscribe.aggregators.myyahoo.desc", "My Yahoo!");
+user_pref("google.toolbar.subscribe.aggregators.myyahoo.id", "myyahoo");
+user_pref("google.toolbar.subscribe.aggregators.myyahoo.order", "3");
+user_pref("google.toolbar.subscribe.aggregators.myyahoo.title", "My Yahoo");
+user_pref("google.toolbar.subscribe.aggregators.myyahoo.url", "http://add.my.yahoo.com/rss?url=%feed%");
+user_pref("google.toolbar.subscribe.aggregators.newsgator.desc", "NewsGator Online");
+user_pref("google.toolbar.subscribe.aggregators.newsgator.id", "newsgator");
+user_pref("google.toolbar.subscribe.aggregators.newsgator.order", "4");
+user_pref("google.toolbar.subscribe.aggregators.newsgator.title", "NewsGator");
+user_pref("google.toolbar.subscribe.aggregators.newsgator.url", "http://www.newsgator.com/ngs/subscriber/subext.aspx?url=%feed%");
+user_pref("google.toolbar.subscribe.aggregators.pluck.desc", "Pluck personal web information center");
+user_pref("google.toolbar.subscribe.aggregators.pluck.id", "pluck");
+user_pref("google.toolbar.subscribe.aggregators.pluck.order", "5");
+user_pref("google.toolbar.subscribe.aggregators.pluck.title", "Pluck");
+user_pref("google.toolbar.subscribe.aggregators.pluck.url", "http://client.pluck.com/pluckit/prompt.aspx?GCID=C12286x053&a=%feed%");
+user_pref("google.toolbar.subscribe.defaultid", "iGoogle");
+user_pref("google.toolbar.subscribe.lastrefreshed", "Mon Oct 09 2006 13:25:18 GMT+0100 (GMT Daylight Time)");
+user_pref("intl.charsetmenu.browser.cache", "ISO-8859-2, UTF-16LE, us-ascii, UTF-8, ISO-8859-15");
+user_pref("network.cookie.prefsMigrated", true);
+user_pref("pref.browser.homepage.disable_button.current_page", false);
+user_pref("pref.privacy.disable_button.clear_cache", false);
+user_pref("print.print_printer", "Microsoft Office Document Image Writer");
+user_pref("print.printer_Microsoft_Office_Document_Image_Writer.print_bgcolor", false);
+user_pref("print.printer_Microsoft_Office_Document_Image_Writer.print_bgimages", false);
+user_pref("print.printer_Microsoft_Office_Document_Image_Writer.print_command", "");
+user_pref("print.printer_Microsoft_Office_Document_Image_Writer.print_downloadfonts", true);
+user_pref("print.printer_Microsoft_Office_Document_Image_Writer.print_evenpages", true);
+user_pref("print.printer_Microsoft_Office_Document_Image_Writer.print_footercenter", "");
+user_pref("print.printer_Microsoft_Office_Document_Image_Writer.print_footerleft", "&PT");
+user_pref("print.printer_Microsoft_Office_Document_Image_Writer.print_footerright", "&D");
+user_pref("print.printer_Microsoft_Office_Document_Image_Writer.print_headercenter", "");
+user_pref("print.printer_Microsoft_Office_Document_Image_Writer.print_headerleft", "&T");
+user_pref("print.printer_Microsoft_Office_Document_Image_Writer.print_headerright", "&U");
+user_pref("print.printer_Microsoft_Office_Document_Image_Writer.print_in_color", true);
+user_pref("print.printer_Microsoft_Office_Document_Image_Writer.print_margin_bottom", "0.5");
+user_pref("print.printer_Microsoft_Office_Document_Image_Writer.print_margin_left", "0.5");
+user_pref("print.printer_Microsoft_Office_Document_Image_Writer.print_margin_right", "0.5");
+user_pref("print.printer_Microsoft_Office_Document_Image_Writer.print_margin_top", "0.5");
+user_pref("print.printer_Microsoft_Office_Document_Image_Writer.print_oddpages", true);
+user_pref("print.printer_Microsoft_Office_Document_Image_Writer.print_orientation", 0);
+user_pref("print.printer_Microsoft_Office_Document_Image_Writer.print_pagedelay", 500);
+user_pref("print.printer_Microsoft_Office_Document_Image_Writer.print_paper_data", 1);
+user_pref("print.printer_Microsoft_Office_Document_Image_Writer.print_paper_height", " 11.00");
+user_pref("print.printer_Microsoft_Office_Document_Image_Writer.print_paper_size", 4259897);
+user_pref("print.printer_Microsoft_Office_Document_Image_Writer.print_paper_size_type", 0);
+user_pref("print.printer_Microsoft_Office_Document_Image_Writer.print_paper_size_unit", 0);
+user_pref("print.printer_Microsoft_Office_Document_Image_Writer.print_paper_width", " 8.50");
+user_pref("print.printer_Microsoft_Office_Document_Image_Writer.print_reversed", false);
+user_pref("print.printer_Microsoft_Office_Document_Image_Writer.print_scaling", " 1.00");
+user_pref("print.printer_Microsoft_Office_Document_Image_Writer.print_shrink_to_fit", true);
+user_pref("print.printer_Microsoft_Office_Document_Image_Writer.print_to_file", false);
+user_pref("print.printer_Microsoft_Office_Document_Image_Writer.print_to_filename", "");
+user_pref("security.warn_viewing_mixed", false);
+user_pref("spellchecker.dictionary", "en-US");
+user_pref("urlclassifier.keyupdatetime.https://sb-ssl.google.com/safebrowsing/getkey?client=navclient-auto-ffox2.0.0.1&", 1181234396);
+user_pref("urlclassifier.keyupdatetime.https://sb-ssl.google.com/safebrowsing/newkey", 1212860951);
+user_pref("urlclassifier.tableversion.goog-black-enchash", "1.50318");
+user_pref("urlclassifier.tableversion.goog-black-url", "1.20750");
+user_pref("urlclassifier.tableversion.goog-white-domain", "1.30");
+user_pref("urlclassifier.tableversion.goog-white-url", "1.371");
+user_pref("webdeveloper.custom.1.color", "#ff0000");
+user_pref("webdeveloper.custom.2.color", "#33ff33");
+user_pref("webdeveloper.custom.3.color", "#3333ff");
+user_pref("webdeveloper.custom.4.color", "#ff0000");
+user_pref("webdeveloper.custom.5.color", "#33ff33");
+user_pref("webdeveloper.dashboard.position", "bottom");
+user_pref("webdeveloper.disable.styles.key", "S");
+user_pref("webdeveloper.display.element.information.key", "F");
+user_pref("webdeveloper.edit.color.background", "#ffffff");
+user_pref("webdeveloper.edit.color.text", "#000000");
+user_pref("webdeveloper.edit.css.key", "E");
+user_pref("webdeveloper.edit.font.size", 12);
+user_pref("webdeveloper.edit.update.frequency", 2000);
+user_pref("webdeveloper.error.console.key", "J");
+user_pref("webdeveloper.feature.tooltip.color.background", "#ffff99");
+user_pref("webdeveloper.feature.tooltip.color.border", "#ffcc66");
+user_pref("webdeveloper.feature.tooltip.color.text", "#000000");
+user_pref("webdeveloper.feature.tooltip.opacity", "0.9");
+user_pref("webdeveloper.generated.content.font.size", 12);
+user_pref("webdeveloper.information.tidy", true);
+user_pref("webdeveloper.java.console.key", "O");
+user_pref("webdeveloper.line.guides.color", "#000000");
+user_pref("webdeveloper.magnification.level", "2");
+user_pref("webdeveloper.open.tabs", true);
+user_pref("webdeveloper.populate.form.fields.email", "example@example.com");
+user_pref("webdeveloper.resize.1.description", "800x600");
+user_pref("webdeveloper.resize.1.height", 600);
+user_pref("webdeveloper.resize.1.width", 800);
+user_pref("webdeveloper.resize.count", 1);
+user_pref("webdeveloper.style.information.dashboard", true);
+user_pref("webdeveloper.tool.1.description", "Validate CSS");
+user_pref("webdeveloper.tool.1.url", "http://jigsaw.w3.org/css-validator/validator?profile=css21&warning=0&uri=");
+user_pref("webdeveloper.tool.2.description", "Validate Feed");
+user_pref("webdeveloper.tool.2.url", "http://validator.w3.org/feed/check.cgi?url=");
+user_pref("webdeveloper.tool.3.description", "Validate HTML");
+user_pref("webdeveloper.tool.3.key", "H");
+user_pref("webdeveloper.tool.3.url", "http://validator.w3.org/check?verbose=1&uri=");
+user_pref("webdeveloper.tool.4.description", "Validate Links");
+user_pref("webdeveloper.tool.4.url", "http://validator.w3.org/checklink?check=Check&hide_type=all&summary=on&uri=");
+user_pref("webdeveloper.tool.5.description", "Validate Section 508");
+user_pref("webdeveloper.tool.5.url", "http://www.cynthiasays.com/mynewtester/cynthia.exe?rptmode=-1&url1=");
+user_pref("webdeveloper.tool.6.description", "Validate WAI");
+user_pref("webdeveloper.tool.6.url", "http://www.cynthiasays.com/mynewtester/cynthia.exe?rptmode=2&url1=");
+user_pref("webdeveloper.tool.count", 6);
+user_pref("webdeveloper.toolbar.key", "B");
+user_pref("webdeveloper.validate.local.accessibility.section508", true);
+user_pref("webdeveloper.validate.local.accessibility.wai.priority1", true);
+user_pref("webdeveloper.validate.local.css.profile", "css21");
+user_pref("webdeveloper.validate.local.html.key", "A");
+user_pref("webdeveloper.version", "1.15");
+user_pref("webdeveloper.view.css.key", "C");
+user_pref("webdeveloper.view.source.key", "U");
+user_pref("webdeveloper.view.style.information.key", "Y");
+user_pref("webdeveloper.zoom.in.key", "Z");
+user_pref("webdeveloper.zoom.out.key", "X");
+user_pref("xpinstall.whitelist.add", "");
+user_pref("xpinstall.whitelist.add.103", "");
diff --git a/chrome/test/data/firefox2_profile/signons2.txt b/chrome/test/data/firefox2_profile/signons2.txt
new file mode 100644
index 0000000..cd587d4
--- /dev/null
+++ b/chrome/test/data/firefox2_profile/signons2.txt
@@ -0,0 +1,29 @@
+#2d
+https://www.google.com
+.
+localhost:8080 (corp.google.com)
+
+MDIEEPgAAAAAAAAAAAAAAAAAAAEwFAYIKoZIhvcNAwcECGWa5u4oyD30BAjVjHehzmI1FQ==
+*
+MDoEEPgAAAAAAAAAAAAAAAAAAAEwFAYIKoZIhvcNAwcECIzNoDayvlg8BBDyGwwPHVf4+H5ECFVHSFF7
+
+.
+http://localhost:8080
+loginuser
+MDIEEPgAAAAAAAAAAAAAAAAAAAEwFAYIKoZIhvcNAwcECEFtzZ3poEPfBAhfSWTBcn8uAQ==
+*loginpass
+MDIEEPgAAAAAAAAAAAAAAAAAAAEwFAYIKoZIhvcNAwcECGRF97w1/HhvBAjcYnNUNjWcgA==
+http://localhost:8080
+loginuser
+MDIEEPgAAAAAAAAAAAAAAAAAAAEwFAYIKoZIhvcNAwcECNp5fZWsPu6KBAhiRy4Ma1F9/g==
+*loginpass
+MDIEEPgAAAAAAAAAAAAAAAAAAAEwFAYIKoZIhvcNAwcECGkvYFh0bA7JBAiPYfjWR04V8g==
+http://localhost:8080
+.
+http://localhost
+loginuser
+MDIEEPgAAAAAAAAAAAAAAAAAAAEwFAYIKoZIhvcNAwcECBJM63MpT9rtBAjMCm7qo/EhlA==
+*
+MDIEEPgAAAAAAAAAAAAAAAAAAAEwFAYIKoZIhvcNAwcECH1iF2yH/PbDBAjKtt50MebjIA==
+
+.
diff --git a/chrome/test/data/firefox3_nss/README b/chrome/test/data/firefox3_nss/README
new file mode 100644
index 0000000..b54a99e
--- /dev/null
+++ b/chrome/test/data/firefox3_nss/README
@@ -0,0 +1,13 @@
+The NSPR and NSS DLLs in this directory (mozcrt19.dll, nss3.dll, nssutil3.dll
+plds4.dll, sqlite3.dll, freebl3.dll, nspr4.dll, nssdbm3.dll, plc4.dll, and
+softokn3.dll) come from the Firefox 3.0 distribution for Windows.
+
+The source code of NSPR and NSS, which you may use, modify, and distribute, is
+available to you free-of-charge from www.mozilla.org under the Mozilla Public
+License and other open source software licenses.
+
+The source code of sqlite3.dll is in the public domain.
+
+mozcrt19.dll is the Mozilla Custom C Runtime, in which Mozilla replaced the
+default allocator with jemalloc. mozcrt19.dll is distributed in the object
+code form only and as part of the NSPR and NSS DLLs.
diff --git a/chrome/test/data/firefox3_nss/freebl3.dll b/chrome/test/data/firefox3_nss/freebl3.dll
new file mode 100644
index 0000000..cd9a4f9
--- /dev/null
+++ b/chrome/test/data/firefox3_nss/freebl3.dll
Binary files differ
diff --git a/chrome/test/data/firefox3_nss/mozcrt19.dll b/chrome/test/data/firefox3_nss/mozcrt19.dll
new file mode 100644
index 0000000..c6c2fb1
--- /dev/null
+++ b/chrome/test/data/firefox3_nss/mozcrt19.dll
Binary files differ
diff --git a/chrome/test/data/firefox3_nss/nspr4.dll b/chrome/test/data/firefox3_nss/nspr4.dll
new file mode 100644
index 0000000..156e23a
--- /dev/null
+++ b/chrome/test/data/firefox3_nss/nspr4.dll
Binary files differ
diff --git a/chrome/test/data/firefox3_nss/nss3.dll b/chrome/test/data/firefox3_nss/nss3.dll
new file mode 100644
index 0000000..e1e23e1
--- /dev/null
+++ b/chrome/test/data/firefox3_nss/nss3.dll
Binary files differ
diff --git a/chrome/test/data/firefox3_nss/nssdbm3.dll b/chrome/test/data/firefox3_nss/nssdbm3.dll
new file mode 100644
index 0000000..d7b9ab8
--- /dev/null
+++ b/chrome/test/data/firefox3_nss/nssdbm3.dll
Binary files differ
diff --git a/chrome/test/data/firefox3_nss/nssutil3.dll b/chrome/test/data/firefox3_nss/nssutil3.dll
new file mode 100644
index 0000000..41d5cf7
--- /dev/null
+++ b/chrome/test/data/firefox3_nss/nssutil3.dll
Binary files differ
diff --git a/chrome/test/data/firefox3_nss/plc4.dll b/chrome/test/data/firefox3_nss/plc4.dll
new file mode 100644
index 0000000..2e11cbc
--- /dev/null
+++ b/chrome/test/data/firefox3_nss/plc4.dll
Binary files differ
diff --git a/chrome/test/data/firefox3_nss/plds4.dll b/chrome/test/data/firefox3_nss/plds4.dll
new file mode 100644
index 0000000..2e93aed
--- /dev/null
+++ b/chrome/test/data/firefox3_nss/plds4.dll
Binary files differ
diff --git a/chrome/test/data/firefox3_nss/softokn3.dll b/chrome/test/data/firefox3_nss/softokn3.dll
new file mode 100644
index 0000000..e29e42d
--- /dev/null
+++ b/chrome/test/data/firefox3_nss/softokn3.dll
Binary files differ
diff --git a/chrome/test/data/firefox3_nss/sqlite3.dll b/chrome/test/data/firefox3_nss/sqlite3.dll
new file mode 100644
index 0000000..5262876
--- /dev/null
+++ b/chrome/test/data/firefox3_nss/sqlite3.dll
Binary files differ
diff --git a/chrome/test/data/firefox3_profile/cert8.db b/chrome/test/data/firefox3_profile/cert8.db
new file mode 100644
index 0000000..ac40a33
--- /dev/null
+++ b/chrome/test/data/firefox3_profile/cert8.db
Binary files differ
diff --git a/chrome/test/data/firefox3_profile/cookies.sqlite b/chrome/test/data/firefox3_profile/cookies.sqlite
new file mode 100644
index 0000000..f9ec2f5
--- /dev/null
+++ b/chrome/test/data/firefox3_profile/cookies.sqlite
Binary files differ
diff --git a/chrome/test/data/firefox3_profile/key3.db b/chrome/test/data/firefox3_profile/key3.db
new file mode 100644
index 0000000..6788cae
--- /dev/null
+++ b/chrome/test/data/firefox3_profile/key3.db
Binary files differ
diff --git a/chrome/test/data/firefox3_profile/places.sqlite b/chrome/test/data/firefox3_profile/places.sqlite
new file mode 100644
index 0000000..9540a3e
--- /dev/null
+++ b/chrome/test/data/firefox3_profile/places.sqlite
Binary files differ
diff --git a/chrome/test/data/firefox3_profile/prefs.js b/chrome/test/data/firefox3_profile/prefs.js
new file mode 100644
index 0000000..c65a9be2
--- /dev/null
+++ b/chrome/test/data/firefox3_profile/prefs.js
@@ -0,0 +1,32 @@
+# Mozilla User Preferences
+
+/* Do not edit this file.
+ *
+ * If you make changes to this file while the application is running,
+ * the changes will be overwritten when the application exits.
+ *
+ * To make a manual change to preferences, you can visit the URL about:config
+ * For more information, see http://www.mozilla.org/unix/customizing.html#prefs
+ */
+
+user_pref("app.update.lastUpdateTime.addon-background-update-timer", 1211306768);
+user_pref("app.update.lastUpdateTime.background-update-timer", 1211306767);
+user_pref("app.update.lastUpdateTime.blocklist-background-update-timer", 1211306767);
+user_pref("app.update.lastUpdateTime.microsummary-generator-update-timer", 1211306768);
+user_pref("app.update.lastUpdateTime.search-engine-update-timer", 1211306768);
+user_pref("browser.migration.version", 1);
+user_pref("browser.places.importBookmarksHTML", false);
+user_pref("browser.places.importDefaults", false);
+user_pref("browser.places.leftPaneFolderId", -1);
+user_pref("browser.places.migratePostDataAnnotations", false);
+user_pref("browser.places.smartBookmarksVersion", 1);
+user_pref("browser.places.updateRecentTagsUri", false);
+user_pref("browser.search.selectedEngine", "IMDB");
+user_pref("browser.search.useDBForOrder", true);
+user_pref("browser.sessionstore.resume_session_once", true);
+user_pref("browser.startup.homepage_override.mstone", "rv:1.9");
+user_pref("extensions.enabledItems", "{972ce4c6-7e08-4474-a285-3208198ce6fd}:3.0");
+user_pref("extensions.lastAppVersion", "3.0");
+user_pref("intl.charsetmenu.browser.cache", "UTF-8");
+user_pref("network.cookie.prefsMigrated", true);
+user_pref("urlclassifier.keyupdatetime.https://sb-ssl.google.com/safebrowsing/newkey", 1213898771);
diff --git a/chrome/test/data/firefox3_profile/search.sqlite b/chrome/test/data/firefox3_profile/search.sqlite
new file mode 100644
index 0000000..55d45cb
--- /dev/null
+++ b/chrome/test/data/firefox3_profile/search.sqlite
Binary files differ
diff --git a/chrome/test/data/firefox3_profile/secmod.db b/chrome/test/data/firefox3_profile/secmod.db
new file mode 100644
index 0000000..cb8cc20
--- /dev/null
+++ b/chrome/test/data/firefox3_profile/secmod.db
Binary files differ
diff --git a/chrome/test/data/firefox3_profile/signons3.txt b/chrome/test/data/firefox3_profile/signons3.txt
new file mode 100644
index 0000000..62cf2c8
--- /dev/null
+++ b/chrome/test/data/firefox3_profile/signons3.txt
@@ -0,0 +1,18 @@
+#2e
+.
+http://localhost:8080
+loginuser
+MDIEEPgAAAAAAAAAAAAAAAAAAAEwFAYIKoZIhvcNAwcECCZ75mS/2HwhBAj+/bq+5rbwnA==
+*loginpass
+MDIEEPgAAAAAAAAAAAAAAAAAAAEwFAYIKoZIhvcNAwcECBLe/6FaBaeiBAhSpECjLu7u0Q==
+http://localhost:8080
+---
+.
+http://localhost:8080 (localhost)
+
+MDIEEPgAAAAAAAAAAAAAAAAAAAEwFAYIKoZIhvcNAwcECE6NmWUq+BITBAhvbI1J3RKb6Q==
+*
+MDoEEPgAAAAAAAAAAAAAAAAAAAEwFAYIKoZIhvcNAwcECFckjT05RJ8uBBCWqEqv8ciEPf+Q8Fpgbtpf
+
+---
+.
diff --git a/chrome/test/data/focus/page_steals_focus.html b/chrome/test/data/focus/page_steals_focus.html
new file mode 100644
index 0000000..46963a0
--- /dev/null
+++ b/chrome/test/data/focus/page_steals_focus.html
@@ -0,0 +1,55 @@
+<html>
+
+ <head>
+<title>This page steals the focus</title>
+</head>
+<body onload="onLoad()">
+
+<script language="javascript" type="text/javascript">
+<!--
+
+var count = 1;
+
+function onLoad() {
+ updateText();
+ setTimeout("loop()", 1000);
+}
+
+function updateText() {
+ var text_div = document.getElementById("main_text");
+ text_div.innerHTML = "I will steal the focus in " + count + " seconds";
+}
+
+
+function loop() {
+ count--;
+ if (count == 0) {
+ var text_div = document.getElementById("main_text");
+ text_div.innerHTML = "Focus stolen!";
+ stealFocus();
+ } else {
+ updateText();
+ setTimeout("loop()", 1000);
+ }
+}
+
+
+function stealFocus() {
+ var textField = document.getElementById("text_edit");
+ textField.focus();
+}
+
+// -->
+</script>
+
+<h1>Welcome to Focus Taker!</h1>
+
+<div id="main_text"></div>
+
+<form href="nowhere.html">
+ <input name="SearchText" type="text" id="text_edit"></input>
+ <input name="SearchButton" type="button" value="Search" onclick="popitup('http://www.google.com');"></input>
+</form>
+<br>
+
+</html>
diff --git a/chrome/test/data/focus/page_with_focus.html b/chrome/test/data/focus/page_with_focus.html
new file mode 100644
index 0000000..62d5ee9
--- /dev/null
+++ b/chrome/test/data/focus/page_with_focus.html
@@ -0,0 +1,24 @@
+<html>
+<head><title>A simple page with the focus on a text edit</title></head>
+
+<script>
+ function init() {
+ document.f.q.focus();
+ }
+</script>
+
+<body onload="init()">
+
+ <h1>Hello</h1>
+ Search:
+ <form name=f>
+ <input name=q size=55 title="Google Search" value=""><br>
+ <form>
+
+ <a href="http://www.google.com">Google</a>&nbsp;&nbsp;
+ <a href="http://mail.google.com">GMail</a>&nbsp;&nbsp;
+ <a href="http://maps.google.com">GMap</a>
+</body>
+
+
+</html>
diff --git a/chrome/test/data/focus/typical_page.html b/chrome/test/data/focus/typical_page.html
new file mode 100644
index 0000000..15b97b0
--- /dev/null
+++ b/chrome/test/data/focus/typical_page.html
@@ -0,0 +1,47 @@
+<html>
+<head><title>Your typical HTML page</title></head>
+
+<script>
+ var focused_elem = "";
+
+ function setFocusedElem(id) {
+ focused_elem = id;
+ updateLog();
+ }
+
+ function clearFocus() {
+ focused_elem = "";
+ updateLog();
+ }
+
+ function getFocusedElement() {
+ return focused_elem;
+ }
+
+ function updateLog() {
+ document.getElementById("log").innerHTML = "Focused element: " + focused_elem;
+ }
+
+</script>
+
+<body>
+
+ <h1>Hello</h1>
+ Search:
+ <form name=f>
+ <input name=q size=55 title="Google Search" value="" id="textEdit" onfocus="setFocusedElem(this.id)" onblur="clearFocus()"><br>
+ <input type=button value="Search" id="searchButton" onfocus="setFocusedElem(this.id)" onblur="clearFocus()">
+ <input type=button value="I am feeling lucky" id="luckyButton" onfocus="setFocusedElem(this.id)" onblur="clearFocus()">
+ <form>
+ <br><br>
+
+ <a href="http://www.google.com" id="googleLink" onfocus="setFocusedElem(this.id)" onblur="clearFocus()">Google</a>&nbsp;&nbsp;
+ <a href="http://mail.google.com" id="gmailLink" onfocus="setFocusedElem(this.id)" onblur="clearFocus()">GMail</a>&nbsp;&nbsp;
+ <a href="http://maps.google.com" id="gmapLink" onfocus="setFocusedElem(this.id)" onblur="clearFocus()">GMap</a>
+
+ <br><br><br>
+ <div id="log"><div>
+</body>
+
+</html>
+
diff --git a/chrome/test/data/frame_dom_access/frame_dom_access.html b/chrome/test/data/frame_dom_access/frame_dom_access.html
new file mode 100644
index 0000000..931acf5
--- /dev/null
+++ b/chrome/test/data/frame_dom_access/frame_dom_access.html
@@ -0,0 +1,6 @@
+<HTML>
+ <BODY>
+ <INPUT id="myinput"> </INPUT>
+ <IFRAME src="frame_level_1.html"/>
+ </BODY>
+</HTML>
diff --git a/chrome/test/data/frame_dom_access/frame_level_1.html b/chrome/test/data/frame_dom_access/frame_level_1.html
new file mode 100644
index 0000000..1dbeb9a
--- /dev/null
+++ b/chrome/test/data/frame_dom_access/frame_level_1.html
@@ -0,0 +1,6 @@
+<HTML>
+ <BODY>
+ <span id="myspan"></span>
+ <iframe src="frame_level_2.html"/>
+ </BODY>
+</HTML>
diff --git a/chrome/test/data/frame_dom_access/frame_level_2.html b/chrome/test/data/frame_dom_access/frame_level_2.html
new file mode 100644
index 0000000..afd7049
--- /dev/null
+++ b/chrome/test/data/frame_dom_access/frame_level_2.html
@@ -0,0 +1,5 @@
+<HTML>
+ <BODY>
+ <DIV id="mydiv"></DIV>
+ </BODY>
+</HTML>
diff --git a/chrome/test/data/google/google.html b/chrome/test/data/google/google.html
new file mode 100644
index 0000000..6fda776
--- /dev/null
+++ b/chrome/test/data/google/google.html
@@ -0,0 +1,17 @@
+<html><head><meta http-equiv="content-type" content="text/html; charset=UTF-8"><title>Google</title><style><!--
+body,td,a,p,.h{font-family:arial,sans-serif}
+.h{font-size:20px}
+.h{color:#3366cc}
+.q{color:#00c}
+--></style>
+<script defer="defer">
+<!--
+function sf(){document.f.q.focus();}
+window.rwt=function(b,d,f,j,k,g,l){var a=window.encodeURIComponent?encodeURIComponent:escape,h="",i="",c=b.href.split("#"),e="";if(d){h="&oi="+a(d)}if(f){i="&cad="+a(f)}if(g){e="&usg="+g}b.href="/url?sa=t"+h+i+"&ct="+a(j)+"&cd="+a(k)+"&url="+a(c[0]).replace(/\+/g,"%2B")+"&ei=qmSARdamFcf2YIrlwKoE"+e+l+(c[1]?"#"+c[1]:"");b.onmousedown="";return true};// -->
+</script></head><body onload="sf()" topmargin="3" alink="#ff0000" bgcolor="#ffffff" link="#0000cc" marginheight="3" text="#000000" vlink="#551a8b"><center><div nowrap="" style="padding-bottom: 4px;" width="100%" align="right"><font size="-1"><b>yourmom@gmail.com</b>&nbsp;|&nbsp;<a href="http://www.google.com/url?sa=p&amp;pref=ig&amp;pval=3&amp;q=http://www.google.com/ig%3Fhl%3Den&amp;usg=__yvmOvIrk79QYmDkrJAeuYO8jTmo=" onmousedown="return rwt(this,'promos','hppphou:en_us','pro','1','__zxxGHEJmJoAKTnuqkUevLLYrO4g=','&sig2=81iEbSYzM_7fDQpy6xZaIg')">Personalized Home</a>&nbsp;|&nbsp;<a href="https://www.google.com/accounts/ManageAccount">My Account</a>&nbsp;|&nbsp;<a href="http://www.google.com/accounts/Logout?continue=http://www.google.com/">Sign out</a></font></div><img alt="Google" src="logo.gif" height="110" width="276"><br><br><form action="/search" name="f"><script defer="defer"><!--
+function qs(el){if(window.RegExp&&window.encodeURIComponent){var ue=el.href,qe=encodeURIComponent(document.f.q.value);if(ue.indexOf("q=")!=-1){el.href=ue.replace(new RegExp("q=[^&$]*"),"q="+qe);}else{el.href=ue+"&q="+qe;}}return 1;}
+function togDisp(e){stopB(e);var elems=document.getElementsByName('more');for(var i=0;i<elems.length;i++){var obj=elems[i],dp="";if(obj.style.display==""){dp="none";}obj.style.display=dp;}return false;}
+function stopB(e){if(!e)e=window.event;e.cancelBubble=true;}
+document.onclick=function(event){var elems=document.getElementsByName('more');if(elems[0].style.display==""){togDisp(event);}}
+//-->
+</script><table border="0" cellpadding="4" cellspacing="0"><tbody><tr><td nowrap="nowrap"><font size="-1"><b>Web</b>&nbsp;&nbsp;&nbsp;&nbsp;<a class="q" href="http://images.google.com/imghp?ie=UTF-8&amp;oe=UTF-8&amp;hl=en&amp;tab=wi" onclick="return qs(this);">Images</a>&nbsp;&nbsp;&nbsp;&nbsp;<a class="q" href="http://video.google.com/?ie=UTF-8&amp;oe=UTF-8&amp;hl=en&amp;tab=wv" onclick="return qs(this);">Video</a>&nbsp;&nbsp;&nbsp;&nbsp;<a class="q" href="http://news.google.com/nwshp?ie=UTF-8&amp;oe=UTF-8&amp;hl=en&amp;tab=wn" onclick="return qs(this);">News</a>&nbsp;&nbsp;&nbsp;&nbsp;<a class="q" href="http://www.google.com/maps?ie=UTF-8&amp;oe=UTF-8&amp;hl=en&amp;tab=wl" onclick="return qs(this);">Maps</a>&nbsp;&nbsp;&nbsp;&nbsp;<!--"/*"/*--><font size="-1"><a class="q" onclick="return window.qs?qs(this):1" href="http://127.0.0.1:4664/&amp;s=oTNhxyxrnKvgsKLBW5ECAV9apZw">Desktop</a></font>&nbsp;&nbsp;&nbsp;&nbsp;<font size="-1"><a class="q" href="http://search/">Moma</a></font>&nbsp;&nbsp;&nbsp;&nbsp;<b><a href="http://www.google.com/intl/en/options/" class="q" onclick="this.blur();return togDisp(event);">more&nbsp;»</a></b><span name="more" id="more" style="border: 1px solid rgb(51, 102, 153); margin: -0.5ex 2ex; padding: 0pt 0pt 0.5ex 0.8ex; background: rgb(255, 255, 255) none repeat scroll 0%; display: none; position: absolute; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; width: 16ex; line-height: 1.9; z-index: 1000;" onclick="stopB(event);"><a href="#" onclick="return togDisp(event);"><img src="x2.gif" alt="Close menu" align="right" border="0" height="12" hspace="4" vspace="4" width="12"></a><a class="q" href="http://books.google.com/bkshp?ie=UTF-8&amp;oe=UTF-8&amp;hl=en&amp;tab=wp" onclick="return qs(this);">Books</a><br><a class="q" href="http://froogle.google.com/frghp?ie=UTF-8&amp;oe=UTF-8&amp;hl=en&amp;tab=wf" onclick="return qs(this);">Froogle</a><br><a class="q" href="http://groups.google.com/grphp?ie=UTF-8&amp;oe=UTF-8&amp;hl=en&amp;tab=wg" onclick="return qs(this);">Groups</a><br><a class="q" href="http://scholar.google.com/schhp?ie=UTF-8&amp;oe=UTF-8&amp;hl=en&amp;tab=ws" onclick="return qs(this);">Scholar</a><br><a href="http://www.google.com/intl/en/options/" class="q"><b>even more »</b></a></span></font></td></tr></tbody></table><table cellpadding="0" cellspacing="0"><tbody><tr valign="top"><td width="25%">&nbsp;</td><td align="center" nowrap="nowrap"><input name="hl" value="en" type="hidden"><input maxlength="2048" name="q" size="55" title="Google Search" value=""><br><input name="btnG" value="Google Search" type="submit"><input name="btnI" value="I'm Feeling Lucky" type="submit"></td><td nowrap="nowrap" width="25%"><font size="-2">&nbsp;&nbsp;<a href="http://www.google.com/advanced_search?hl=en">Advanced Search</a><br>&nbsp;&nbsp;<a href="http://www.google.com/preferences?hl=en">Preferences</a><br>&nbsp;&nbsp;<a href="http://www.google.com/language_tools?hl=en">Language Tools</a></font></td></tr></tbody></table></form><br><font size="-1"><a href="http://maps.google.com/maps?f=l" onmousedown="return rwt(this,'promos','hppweb:en_us','pro','1','__cRFkyGl8vmPJFLoVMwLVZG0r-Rs=','&sig2=y1UbGzpOnQEIuHK0FM2ztw')">Google Maps</a>: Find local stores and directions for holiday shopping.</font><br><br><br><font size="-1"><a href="http://www.google.com/intl/en/ads/">Advertising&nbsp;Programs</a> - <a href="http://www.google.com/services/">Business Solutions</a> - <a href="http://www.google.com/intl/en/about.html">About Google</a></font><p><font size="-2">©2006 Google</font></p></center></body></html> \ No newline at end of file
diff --git a/chrome/test/data/google/logo.gif b/chrome/test/data/google/logo.gif
new file mode 100644
index 0000000..afa22bc
--- /dev/null
+++ b/chrome/test/data/google/logo.gif
Binary files differ
diff --git a/chrome/test/data/google/x2.gif b/chrome/test/data/google/x2.gif
new file mode 100644
index 0000000..552b769
--- /dev/null
+++ b/chrome/test/data/google/x2.gif
Binary files differ
diff --git a/chrome/test/data/http_to_file.html b/chrome/test/data/http_to_file.html
new file mode 100644
index 0000000..c3062e4
--- /dev/null
+++ b/chrome/test/data/http_to_file.html
@@ -0,0 +1,5 @@
+<!-- Test used by RedirectTest.NoHttpToFile to make sure we don't crash
+and that we don't perform redirections from http to file. See bug 1139823 -->
+<html><head><title>File!</title></head>
+<body></body>
+</html>
diff --git a/chrome/test/data/icon_util/128_X_128_icon.ico b/chrome/test/data/icon_util/128_X_128_icon.ico
new file mode 100644
index 0000000..a5d72fe
--- /dev/null
+++ b/chrome/test/data/icon_util/128_X_128_icon.ico
Binary files differ
diff --git a/chrome/test/data/icon_util/16_X_16_icon.ico b/chrome/test/data/icon_util/16_X_16_icon.ico
new file mode 100644
index 0000000..0e524f1
--- /dev/null
+++ b/chrome/test/data/icon_util/16_X_16_icon.ico
Binary files differ
diff --git a/chrome/test/data/ie@cookie[1].txt b/chrome/test/data/ie@cookie[1].txt
new file mode 100644
index 0000000..84c1df4
--- /dev/null
+++ b/chrome/test/data/ie@cookie[1].txt
@@ -0,0 +1,69 @@
+City
+010
+cookie.com/
+1536
+616982400
+29918725
+2476228016
+29918054
+*
+ID
+0CB7D340F6B05B750CAAD871BA598529
+cookie.com/path/
+1536
+2967774592
+32084998
+910020000
+29880625
+*
+Security
+1
+cookie.com/dir/sub_dir/
+1
+2189574144
+32107986
+2663222448
+29909387
+*
+z2
+dogs!
+~~local~~/C:/Documents%20and%20Settings/filecookie/
+1088
+2189574144
+32107986
+3575890080
+29928395
+*
+WITHPATH
+B
+boink.example.com/~happy
+1600
+2189574144
+32107986
+1637792944
+29932061
+*
+HTTPONLY
+yarz
+boink.example.com/~happy/
+9728
+2189574144
+32107986
+3893915648
+29932062
+*
+invalid_case1
+empty_host
+
+1536
+2319892480
+30251495
+2028928160
+29884415
+*
+broken
+cookie
+shold
+not
+be
+parsed
diff --git a/chrome/test/data/iframe.html b/chrome/test/data/iframe.html
new file mode 100644
index 0000000..a08e34b
--- /dev/null
+++ b/chrome/test/data/iframe.html
@@ -0,0 +1,4 @@
+<html><head><title>iframe test</title></head>
+<body>
+<iframe src="title1.html"/>
+</body></html> \ No newline at end of file
diff --git a/chrome/test/data/iframe_in_empty_frame.html b/chrome/test/data/iframe_in_empty_frame.html
new file mode 100644
index 0000000..854cd1c
--- /dev/null
+++ b/chrome/test/data/iframe_in_empty_frame.html
@@ -0,0 +1,18 @@
+<html><head><title>iframe test</title></head>
+ <script type="text/javascript">
+function createStruct(wnd,viewer,popup){
+ iframe=wnd.document.createElement('iframe');
+ viewer.appendChild(iframe);
+ iframe.contentWindow.document.write('<SCRIPT src=\"iframe_in_empty_frame.js\"></SCR'+'IPT>');
+}
+
+wndname = "_blank";
+wnd = window.open("", wndname, 'width=780,height=572,scrollbars=no,resizeable=no,statusbar=no,status=no,left = '+((screen.width / 2) - 780 / 2)+', var top = '+((screen.height / 2) - 572 / 2)+'');
+if(wnd) {
+ wnd.document.open();
+ wnd.document.write('<html><body onload="finished();"><script>function finished() {if (window.opener) {window.opener.createStruct(this,document.getElementById("viewer"),true);}}</scr'+'ipt><div id="viewer"></div></body></html>');
+ wnd.document.close();
+}
+
+</script>
+</html>
diff --git a/chrome/test/data/iframe_in_empty_frame.js b/chrome/test/data/iframe_in_empty_frame.js
new file mode 100644
index 0000000..110f514
--- /dev/null
+++ b/chrome/test/data/iframe_in_empty_frame.js
@@ -0,0 +1,3 @@
+document.write('');
+document.location.href="http://www.google.com/"
+document.write('');
diff --git a/chrome/test/data/inspector/dummy.js b/chrome/test/data/inspector/dummy.js
new file mode 100644
index 0000000..f84383e
--- /dev/null
+++ b/chrome/test/data/inspector/dummy.js
@@ -0,0 +1,3 @@
+function setCookie() {
+ document.cookie = 'viewsource_cookie=foo';
+}
diff --git a/chrome/test/data/inspector/test1.html b/chrome/test/data/inspector/test1.html
new file mode 100644
index 0000000..a9cf12d
--- /dev/null
+++ b/chrome/test/data/inspector/test1.html
@@ -0,0 +1,4 @@
+<html>
+<body></body>
+This file exists to test that one resource get loaded in Chrome inspector.
+</html> \ No newline at end of file
diff --git a/chrome/test/data/inspector/test2.html b/chrome/test/data/inspector/test2.html
new file mode 100644
index 0000000..21de21b
--- /dev/null
+++ b/chrome/test/data/inspector/test2.html
@@ -0,0 +1,5 @@
+<html>
+<head><script src="dummy.js"></script></head>
+<body onload="setCookie();"></body>
+This file exists to test that two resources get loaded in Chrome inspector.
+</html> \ No newline at end of file
diff --git a/chrome/test/data/interstitial_page/google.html b/chrome/test/data/interstitial_page/google.html
new file mode 100644
index 0000000..6fda776
--- /dev/null
+++ b/chrome/test/data/interstitial_page/google.html
@@ -0,0 +1,17 @@
+<html><head><meta http-equiv="content-type" content="text/html; charset=UTF-8"><title>Google</title><style><!--
+body,td,a,p,.h{font-family:arial,sans-serif}
+.h{font-size:20px}
+.h{color:#3366cc}
+.q{color:#00c}
+--></style>
+<script defer="defer">
+<!--
+function sf(){document.f.q.focus();}
+window.rwt=function(b,d,f,j,k,g,l){var a=window.encodeURIComponent?encodeURIComponent:escape,h="",i="",c=b.href.split("#"),e="";if(d){h="&oi="+a(d)}if(f){i="&cad="+a(f)}if(g){e="&usg="+g}b.href="/url?sa=t"+h+i+"&ct="+a(j)+"&cd="+a(k)+"&url="+a(c[0]).replace(/\+/g,"%2B")+"&ei=qmSARdamFcf2YIrlwKoE"+e+l+(c[1]?"#"+c[1]:"");b.onmousedown="";return true};// -->
+</script></head><body onload="sf()" topmargin="3" alink="#ff0000" bgcolor="#ffffff" link="#0000cc" marginheight="3" text="#000000" vlink="#551a8b"><center><div nowrap="" style="padding-bottom: 4px;" width="100%" align="right"><font size="-1"><b>yourmom@gmail.com</b>&nbsp;|&nbsp;<a href="http://www.google.com/url?sa=p&amp;pref=ig&amp;pval=3&amp;q=http://www.google.com/ig%3Fhl%3Den&amp;usg=__yvmOvIrk79QYmDkrJAeuYO8jTmo=" onmousedown="return rwt(this,'promos','hppphou:en_us','pro','1','__zxxGHEJmJoAKTnuqkUevLLYrO4g=','&sig2=81iEbSYzM_7fDQpy6xZaIg')">Personalized Home</a>&nbsp;|&nbsp;<a href="https://www.google.com/accounts/ManageAccount">My Account</a>&nbsp;|&nbsp;<a href="http://www.google.com/accounts/Logout?continue=http://www.google.com/">Sign out</a></font></div><img alt="Google" src="logo.gif" height="110" width="276"><br><br><form action="/search" name="f"><script defer="defer"><!--
+function qs(el){if(window.RegExp&&window.encodeURIComponent){var ue=el.href,qe=encodeURIComponent(document.f.q.value);if(ue.indexOf("q=")!=-1){el.href=ue.replace(new RegExp("q=[^&$]*"),"q="+qe);}else{el.href=ue+"&q="+qe;}}return 1;}
+function togDisp(e){stopB(e);var elems=document.getElementsByName('more');for(var i=0;i<elems.length;i++){var obj=elems[i],dp="";if(obj.style.display==""){dp="none";}obj.style.display=dp;}return false;}
+function stopB(e){if(!e)e=window.event;e.cancelBubble=true;}
+document.onclick=function(event){var elems=document.getElementsByName('more');if(elems[0].style.display==""){togDisp(event);}}
+//-->
+</script><table border="0" cellpadding="4" cellspacing="0"><tbody><tr><td nowrap="nowrap"><font size="-1"><b>Web</b>&nbsp;&nbsp;&nbsp;&nbsp;<a class="q" href="http://images.google.com/imghp?ie=UTF-8&amp;oe=UTF-8&amp;hl=en&amp;tab=wi" onclick="return qs(this);">Images</a>&nbsp;&nbsp;&nbsp;&nbsp;<a class="q" href="http://video.google.com/?ie=UTF-8&amp;oe=UTF-8&amp;hl=en&amp;tab=wv" onclick="return qs(this);">Video</a>&nbsp;&nbsp;&nbsp;&nbsp;<a class="q" href="http://news.google.com/nwshp?ie=UTF-8&amp;oe=UTF-8&amp;hl=en&amp;tab=wn" onclick="return qs(this);">News</a>&nbsp;&nbsp;&nbsp;&nbsp;<a class="q" href="http://www.google.com/maps?ie=UTF-8&amp;oe=UTF-8&amp;hl=en&amp;tab=wl" onclick="return qs(this);">Maps</a>&nbsp;&nbsp;&nbsp;&nbsp;<!--"/*"/*--><font size="-1"><a class="q" onclick="return window.qs?qs(this):1" href="http://127.0.0.1:4664/&amp;s=oTNhxyxrnKvgsKLBW5ECAV9apZw">Desktop</a></font>&nbsp;&nbsp;&nbsp;&nbsp;<font size="-1"><a class="q" href="http://search/">Moma</a></font>&nbsp;&nbsp;&nbsp;&nbsp;<b><a href="http://www.google.com/intl/en/options/" class="q" onclick="this.blur();return togDisp(event);">more&nbsp;»</a></b><span name="more" id="more" style="border: 1px solid rgb(51, 102, 153); margin: -0.5ex 2ex; padding: 0pt 0pt 0.5ex 0.8ex; background: rgb(255, 255, 255) none repeat scroll 0%; display: none; position: absolute; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; width: 16ex; line-height: 1.9; z-index: 1000;" onclick="stopB(event);"><a href="#" onclick="return togDisp(event);"><img src="x2.gif" alt="Close menu" align="right" border="0" height="12" hspace="4" vspace="4" width="12"></a><a class="q" href="http://books.google.com/bkshp?ie=UTF-8&amp;oe=UTF-8&amp;hl=en&amp;tab=wp" onclick="return qs(this);">Books</a><br><a class="q" href="http://froogle.google.com/frghp?ie=UTF-8&amp;oe=UTF-8&amp;hl=en&amp;tab=wf" onclick="return qs(this);">Froogle</a><br><a class="q" href="http://groups.google.com/grphp?ie=UTF-8&amp;oe=UTF-8&amp;hl=en&amp;tab=wg" onclick="return qs(this);">Groups</a><br><a class="q" href="http://scholar.google.com/schhp?ie=UTF-8&amp;oe=UTF-8&amp;hl=en&amp;tab=ws" onclick="return qs(this);">Scholar</a><br><a href="http://www.google.com/intl/en/options/" class="q"><b>even more »</b></a></span></font></td></tr></tbody></table><table cellpadding="0" cellspacing="0"><tbody><tr valign="top"><td width="25%">&nbsp;</td><td align="center" nowrap="nowrap"><input name="hl" value="en" type="hidden"><input maxlength="2048" name="q" size="55" title="Google Search" value=""><br><input name="btnG" value="Google Search" type="submit"><input name="btnI" value="I'm Feeling Lucky" type="submit"></td><td nowrap="nowrap" width="25%"><font size="-2">&nbsp;&nbsp;<a href="http://www.google.com/advanced_search?hl=en">Advanced Search</a><br>&nbsp;&nbsp;<a href="http://www.google.com/preferences?hl=en">Preferences</a><br>&nbsp;&nbsp;<a href="http://www.google.com/language_tools?hl=en">Language Tools</a></font></td></tr></tbody></table></form><br><font size="-1"><a href="http://maps.google.com/maps?f=l" onmousedown="return rwt(this,'promos','hppweb:en_us','pro','1','__cRFkyGl8vmPJFLoVMwLVZG0r-Rs=','&sig2=y1UbGzpOnQEIuHK0FM2ztw')">Google Maps</a>: Find local stores and directions for holiday shopping.</font><br><br><br><font size="-1"><a href="http://www.google.com/intl/en/ads/">Advertising&nbsp;Programs</a> - <a href="http://www.google.com/services/">Business Solutions</a> - <a href="http://www.google.com/intl/en/about.html">About Google</a></font><p><font size="-2">©2006 Google</font></p></center></body></html> \ No newline at end of file
diff --git a/chrome/test/data/interstitial_page/interstitial.html b/chrome/test/data/interstitial_page/interstitial.html
new file mode 100644
index 0000000..bc22ecf
--- /dev/null
+++ b/chrome/test/data/interstitial_page/interstitial.html
@@ -0,0 +1,7 @@
+<html>
+<head><title>Interstitial page</title></head>
+<body>
+ <h1>This is a phony interstitial page</h1>
+ Hope you are enjoying it!
+</body>
+</html> \ No newline at end of file
diff --git a/chrome/test/data/interstitial_page/logo.gif b/chrome/test/data/interstitial_page/logo.gif
new file mode 100644
index 0000000..afa22bc
--- /dev/null
+++ b/chrome/test/data/interstitial_page/logo.gif
Binary files differ
diff --git a/chrome/test/data/interstitial_page/shopping.html b/chrome/test/data/interstitial_page/shopping.html
new file mode 100644
index 0000000..8cb250f
--- /dev/null
+++ b/chrome/test/data/interstitial_page/shopping.html
@@ -0,0 +1,123 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html><head>
+
+<style type="text/css">
+<!--
+.productname { font-size: 20px; font-weight: bold; color: #1D46AA; font-family: arial,sans-serif}
+-->
+</style>
+
+
+
+<meta http-equiv="content-type" content="text/html; charset=utf-8"><title>Google Product Search</title>
+
+<script type="text/javascript">
+function sf(){document.f.q.focus();}
+function c(p,l,e){var f=document.f;if (f.action && document.getElementById) {var hf=document.getElementById("hf");if (hf) {var t = "<input type=hidden name=tab value="+l+">";hf.innerHTML=t;}f.action = 'http://'+p;e.cancelBubble=true;f.submit();return false;}return true;}
+function ss(w){window.status=w;return true;}
+function cs(){window.status='';}
+function ga(o,e){if (document.getElementById){a=o.id.substring(1); p = "";r = "";g = e.target;if (g) { t = g.id;f = g.parentNode;if (f) {p = f.id;h = f.parentNode;if (h) r = h.id;}} else{h = e.srcElement;f = h.parentNode;if (f) p = f.id;t = h.id;}if (t==a || p==a || r==a) return true;location.href=document.getElementById(a).href}}
+function postAddToShoppingList(formId) { var elm = document.getElementById(formId); elm.submit(); }
+</script>
+<link type="text/css" rel="stylesheet" href="shopping_files/froogle.css">
+<style type="text/css">
+#q{width:22.5em}
+</style>
+<script>window.gbar={};(function(){function o(a,e,d){var b="on"+e;if(a.addEventListener){a.addEventListener(e,d,false)}else if(a.attachEvent){a.attachEvent(b,d)}else{var i=a[b];a[b]=function(){var f=i.apply(this,arguments),h=d.apply(this,arguments);return f==undefined?h:(h==undefined?f:h&&f)}}};var j=window.gbar,c,l,g;function m(a,e,d){a.display=a.display=="block"?"none":"block";a.left=e+"px";a.top=d+"px"}j.tg=function(a){var e=0,d,b,i,f=0,h=window.navExtra;!l&&(l=document.getElementById("gbar"));!g&&(g=l.getElementsByTagName("span"));(a||window.event).cancelBubble=true;if(!c){c=document.createElement(Array.every||window.createPopup?"iframe":"div");c.frameBorder="0";c.id="gbi";c.scrolling="no";c.src="javascript:''";document.body.appendChild(c);if(h&&g[8])for(var n in h){var k=document.createElement("span");k.appendChild(h[n]);k.className="gb2";g[0].parentNode.insertBefore(k,g[8])}o(document,"click",j.close)}for(;g[f];f++){b=g[f];i=b.className;if(i=="gb3"){d=b.offsetLeft;while(b=b.offsetParent)d+=b.offsetLeft;m(c.style,d,24)}else if(i=="gb2"){if(!(g[f].firstChild.tagName=="A")){b.style.padding=".2em .5em"}m(b.style,d+1,25+e);e+=20}}c.style.height=e+"px"};j.close=function(a){c&&c.style.display=="block"&&j.tg(a)};})();</script>
+<style>#gbar{float:left;font-weight:bold;height:22px;padding-left:2px}#gbh{border-top:1px solid #c9d7f1;font-size:0;height:0;position:absolute;right:0;top:24px;width:200%}#gbi{background:#fff;border:1px solid;border-color:#c9d7f1 #36c #36c #a2bae7;font-size:13px;top:24px;z-index:1000}#guser{padding-bottom:7px !important}#gbar,#guser{font-size:13px;padding-top:1px !important}@media all{.gb1,.gb3{height:22px;margin-right:.73em;vertical-align:top}}#gbi,.gb2{display:none;position:absolute;width:8em}.gb2{z-index:1001}#gbar a,#gbar a:active,#gbar a:visited{color:#00c;font-weight:normal}.gb2 a,.gb3 a{text-decoration:none}.gb2 a{display:block;padding:.2em .5em}#gbar .gb2 a:hover{background:#36c;color:#fff}</style>
+<style type="text/css">#gbar .gbard b{padding:.2em .5em;}</style></head><noscript><meta http-equiv=refresh content="0; URL=/prdhp?tab=wf&output=html"></noscript><body onload="document.f.q.focus();" topmargin="3" alink="#ff0000" bgcolor="#ffffff" link="#0000cc" marginheight="3" text="#000000" vlink="#551a8b">
+<div id="gbar"><nobr><span class="gb1"><a href="http://www.google.com/webhp?tab=fw">Web</a></span> <span class="gb1"><a href="http://images.google.com/imghp?tab=fi">Images</a></span> <span class="gb1"><a href="http://maps.google.com/maps?tab=fl">Maps</a></span> <span class="gb1"><a href="http://news.google.com/nwshp?tab=fn">News</a></span> <span class="gb1">Shopping</span> <span class="gb1"><a href="http://mail.google.com/mail?tab=fm">Gmail</a></span> <span class="gb3"><a href="http://www.google.com/intl/en/options/" onclick="this.blur();gbar.tg(event);return false"><u>more</u> <span style="font-size: 11px;">▼</span></a></span> <span class="gb2"><a href="http://blogsearch.google.com/?tab=fb">Blogs</a></span> <span class="gb2"><a href="http://books.google.com/bkshp?tab=fp">Books</a></span> <span class="gb2"><a href="http://www.google.com/calendar?tab=fc">Calendar</a></span> <span class="gb2"><a href="http://docs.google.com/?tab=fo">Documents</a></span> <span class="gb2"><a href="http://finance.google.com/finance?tab=fe">Finance</a></span> <span class="gb2"><a href="http://groups.google.com/grphp?tab=fg">Groups</a></span> <span class="gb2"><a href="http://picasaweb.google.com/home?tab=fq">Photos</a></span> <span class="gb2"><a href="http://www.google.com/reader?tab=fy">Reader</a></span> <span class="gb2"><a href="http://scholar.google.com/schhp?tab=fs">Scholar</a></span> <span class="gb2"><a href="http://video.google.com/?tab=fv">Video</a></span> <span class="gb2"><a href="http://www.youtube.com/?tab=f1">YouTube</a></span> <span class="gb2"><a href="http://www.google.com/intl/en/options/">even more »</a></span> </nobr></div><div id="gbh"></div>
+<div align="right">
+<nobr><font size="-1">
+<a href="http://www.google.com/shoppinglist">My Shopping List</a></font></nobr>
+</div>
+<br>
+<center>
+<table border="0" cellpadding="0" cellspacing="0" width="100%">
+<tbody><tr>
+<td align="center" valign="bottom">
+<table border="0" cellpadding="0" cellspacing="0">
+<tbody><tr>
+<td align="right"><img src="shopping_files/hp0.gif" alt="Google Product Search" border="0"></td>
+<td><img src="shopping_files/hp1.gif" border="0"></td>
+<td align="left"><img src="shopping_files/hp2.gif" border="0"></td>
+</tr><tr>
+<td align="right" valign="top"><span class="productname"><b>Product Search</b></span></td>
+<td valign="top"><img src="shopping_files/hp3.gif" border="0"></td>
+<td valign="top"><font color="#6f6f6f" size="-1">BETA</font></td>
+</tr>
+</tbody></table>
+<br>
+<form name="f" action="/products">
+<table cellpadding="0" cellspacing="0">
+<tbody><tr valign="top">
+<td width="150">&nbsp;</td>
+<td align="center">
+<input maxlength="256" name="q" size="40" value="">&nbsp;<input name="btnG" value="Search Products" type="submit">
+<span id="hf">
+</span>
+</td>
+<td align="left" nowrap="nowrap" valign="top" width="150">
+<font size="-2">&nbsp;&nbsp;<a href="http://www.google.com/advanced_product_search">Advanced&nbsp;Product&nbsp;Search</a>
+<br>&nbsp;&nbsp;<a href="http://www.google.com/preferences">Preferences</a>
+</font>
+</td>
+</tr>
+</tbody></table>
+</form>
+<h2 style="margin: 1em; font-size: 110%; color: rgb(29, 70, 166); font-weight: bold;">Search for stuff to buy.</h2>
+<p></p><table align="center" cellpadding="3" cellspacing="0" width="630">
+<tbody><tr><td style="border-bottom: 1px solid rgb(51, 102, 204);" colspan="5"><font size="-1">A few of the items recently found with Google Product Search:</font></td></tr>
+<tr>
+<td nowrap="nowrap" width="20"><nobr><font size="-1"><a href="http://www.google.com/products?q=balloons&amp;sampleq=1">balloons</a></font></nobr></td>
+<td nowrap="nowrap" width="20"><nobr><font size="-1"><a href="http://www.google.com/products?q=buckwheat+pillow&amp;sampleq=1">buckwheat&nbsp;pillow</a></font></nobr></td>
+<td nowrap="nowrap" width="20"><nobr><font size="-1"><a href="http://www.google.com/products?q=miter+saw&amp;sampleq=1">miter&nbsp;saw</a></font></nobr></td>
+<td nowrap="nowrap" width="20"><nobr><font size="-1"><a href="http://www.google.com/products?q=firewood+rack&amp;sampleq=1">firewood&nbsp;rack</a></font></nobr></td>
+<td nowrap="nowrap" width="20"><nobr><font size="-1"><a href="http://www.google.com/products?q=nikon+coolpix&amp;sampleq=1">nikon&nbsp;coolpix</a></font></nobr></td>
+</tr>
+<tr>
+<td nowrap="nowrap" width="20"><nobr><font size="-1"><a href="http://www.google.com/products?q=high+chair&amp;sampleq=1">high&nbsp;chair</a></font></nobr></td>
+<td nowrap="nowrap" width="20"><nobr><font size="-1"><a href="http://www.google.com/products?q=sofa+set&amp;sampleq=1">sofa&nbsp;set</a></font></nobr></td>
+<td nowrap="nowrap" width="20"><nobr><font size="-1"><a href="http://www.google.com/products?q=bean+bag&amp;sampleq=1">bean&nbsp;bag</a></font></nobr></td>
+<td nowrap="nowrap" width="20"><nobr><font size="-1"><a href="http://www.google.com/products?q=wine+refrigerator&amp;sampleq=1">wine&nbsp;refrigerator</a></font></nobr></td>
+<td nowrap="nowrap" width="20"><nobr><font size="-1"><a href="http://www.google.com/products?q=chopsticks&amp;sampleq=1">chopsticks</a></font></nobr></td>
+</tr>
+<tr>
+<td nowrap="nowrap" width="20"><nobr><font size="-1"><a href="http://www.google.com/products?q=coffee+grinder&amp;sampleq=1">coffee&nbsp;grinder</a></font></nobr></td>
+<td nowrap="nowrap" width="20"><nobr><font size="-1"><a href="http://www.google.com/products?q=polk+audio&amp;sampleq=1">polk&nbsp;audio</a></font></nobr></td>
+<td nowrap="nowrap" width="20"><nobr><font size="-1"><a href="http://www.google.com/products?q=body+glove+wetsuit&amp;sampleq=1">body&nbsp;glove&nbsp;wetsuit</a></font></nobr></td>
+<td nowrap="nowrap" width="20"><nobr><font size="-1"><a href="http://www.google.com/products?q=grandfather+clocks&amp;sampleq=1">grandfather&nbsp;clocks</a></font></nobr></td>
+<td nowrap="nowrap" width="20"><nobr><font size="-1"><a href="http://www.google.com/products?q=milk+crate&amp;sampleq=1">milk&nbsp;crate</a></font></nobr></td>
+</tr>
+<tr>
+<td nowrap="nowrap" width="20"><nobr><font size="-1"><a href="http://www.google.com/products?q=belgian+chocolate&amp;sampleq=1">belgian&nbsp;chocolate</a></font></nobr></td>
+<td nowrap="nowrap" width="20"><nobr><font size="-1"><a href="http://www.google.com/products?q=measuring+cups&amp;sampleq=1">measuring&nbsp;cups</a></font></nobr></td>
+<td nowrap="nowrap" width="20"><nobr><font size="-1"><a href="http://www.google.com/products?q=backgammon&amp;sampleq=1">backgammon</a></font></nobr></td>
+<td nowrap="nowrap" width="20"><nobr><font size="-1"><a href="http://www.google.com/products?q=hawaiian+shirt&amp;sampleq=1">hawaiian&nbsp;shirt</a></font></nobr></td>
+<td nowrap="nowrap" width="20"><nobr><font size="-1"><a href="http://www.google.com/products?q=hip+flask&amp;sampleq=1">hip&nbsp;flask</a></font></nobr></td>
+</tr>
+<tr>
+<td nowrap="nowrap" width="20"><nobr><font size="-1"><a href="http://www.google.com/products?q=camera+case&amp;sampleq=1">camera&nbsp;case</a></font></nobr></td>
+<td nowrap="nowrap" width="20"><nobr><font size="-1"><a href="http://www.google.com/products?q=replaytv&amp;sampleq=1">replaytv</a></font></nobr></td>
+<td nowrap="nowrap" width="20"><nobr><font size="-1"><a href="http://www.google.com/products?q=dvd+camcorders&amp;sampleq=1">dvd&nbsp;camcorders</a></font></nobr></td>
+<td nowrap="nowrap" width="20"><nobr><font size="-1"><a href="http://www.google.com/products?q=bagless+vacuum&amp;sampleq=1">bagless&nbsp;vacuum</a></font></nobr></td>
+<td nowrap="nowrap" width="20"><nobr><font size="-1"><a href="http://www.google.com/products?q=crystal+chandelier&amp;sampleq=1">crystal&nbsp;chandelier</a></font></nobr></td>
+</tr>
+<tr><td style="border-bottom: 1px solid rgb(51, 102, 204); height: 5px; font-size: 1px;" colspan="5">&nbsp;</td></tr>
+</tbody></table>
+<br>
+<p></p>
+<hr class="z">
+<table border="0" cellpadding="2" cellspacing="0" width="100%">
+<tbody><tr>
+<td align="center">
+<font size="-1"><a href="http://www.google.com/">Google&nbsp;Home</a> -
+<a href="http://www.google.com/base/help/sellongoogle.html">Information&nbsp;for&nbsp;Sellers</a> - <a href="http://www.google.com/products/intl/en_us/about.html">Help</a>
+</font>
+</td>
+</tr>
+</tbody></table>
+<br>
+<font class="p" size="-1">©2007 Google</font>
+
+</td></tr></tbody></table></center></body></html> \ No newline at end of file
diff --git a/chrome/test/data/interstitial_page/shopping_files/froogle.css b/chrome/test/data/interstitial_page/shopping_files/froogle.css
new file mode 100644
index 0000000..db2e22b
--- /dev/null
+++ b/chrome/test/data/interstitial_page/shopping_files/froogle.css
@@ -0,0 +1 @@
+.attr-div{padding:0 0 0 0;margin-bottom:.25em}.attr-table th,.attr-table td{text-align:left;vertical-align:top;font-size:small;white-space:nowrap;padding-right:2em}.attr-div th{font-weight:normal}.attr-table ul,.attr-table li{display:block;margin:0;padding:0;text-indent:0;white-space:nowrap}.directions{white-space:nowrap}.directions a{font-weight:bold}.directions a:visited,.directions a:link{font-weight:normal;color:blue}.directions form{margin-bottom:1em}body,td, div, a, p{font-family:arial, sans-serif}.indent{margin-left:1em;margin-right:1em}.q a:visited,.q a:link, .q a:active, .q{color:#0000cc}.z{display:none}img{border-color:#0000a0}form{margin:0px}.w{white-space:nowrap!important;background-color:white;padding:6px 0}.h{font-size:78%}.g{font-size:83%;border:1px solid #cccccc;font-weight:normal}.c{border-right:1px solid #cccccc;padding:3px 2px 6px 2px}.d{border-left:1px solid #cccccc;padding:3px 2px 6px 2px}.b{font-size:12pt;color:#0000cc;font-weight:bold}.n a{font-size:10pt;color:#000000}.f,.f:link, .f a:link{color:#6f6f6f}.fl:visited{color:#551a8b}.fl:active{color:#f00}.fl:link{color:#7777CC}.fmr:visited{color:#551a8b}.fmr:active{color:#f00}.fmr:link{color:#3366cc}.i,.i:link{color:#a90a08}.n .i{font-size:10pt;font-weight:bold}.t a:link,.t a:active, .t a:visited, .t{color:#000000}.ch{cursor:pointer;cursor:hand}.a,.cp{color:#008000}.cp:visited{color:#551a8b}.cpn:visited{color:#551a8b}.q a:visited,.q a:link, .q a:active, .q{color:#0000cc}.k{background-color:#80c65a}.z{display:none}.j{width:33em}.e{margin-top:.75em;margin-bottom:.75em}.submitLink{color:#00f;background-color:transparent;text-decoration:underline;border:none;cursor:pointer;cursor:hand}.inform{margin:0;padding:0;display:inline}.x{padding-right:10px}.dr{font-size:90%}.de{width:30em}.bo{border-bottom:1px solid #efefef;width:11em}.bot{border-bottom:1px solid #cdcdcd}.ol{border-bottom:1px solid #efefef}.la{margin-top:0.5em}.la td{border-right:1px solid silver;padding-left:10px;padding-right:10px}.la .pad{border-right:0px;height:6px}.la .last{border-right:0px}.la f{color:#6f6f6f}.la .s{font-size:70%}.compare a{background-color:#efefef;width:11em;border-style:outset;border-width:1px;text-align:center;bottom:0px;display:block;padding:1px}.compare a:active,.compare a:focus{border-style:inset}.no{text-decoration:none;color:#000000;font-size:90%}.buy a{width:7em}.pd{padding-bottom:10px}body{background:#fff;color:#000;margin:3px 8px 0 8px}a img{border:0}table{border:0}.store-info,.product-info{font-size:small;width:300px}.store-info td{vertical-align:top}.store-info td.pr,.store-info td.icn{text-align:center;font-size:small;font-weight:bold;width:100px}.store-info td.icn img{width:90px;height:90px}.store-info .name,.product-info .name{font-size:medium;font-weight:normal}.store-info .pr,.product-info .pr{font-size:medium;font-weight:bold}.store-info .ratings a{color:green}.all-stores{text-align:right}.product-info .icon{float:left;margin:5px}#page{margin-top:8px;position:relative}#panel{overflow:auto;width:400px;left:0px}#map{left:410px;border:1px solid #979797}#panel,#map{position:absolute;top:0px}#result .list{width:100%;width:expression(this.offsetParent.clientWidth+'px')}.list{margin:0 0 0.5em 0}.list td{font-size:small;vertical-align:top;padding:2px}.list .bc td{padding:0}.list p{margin:0}.list img{border:0}.list h3{margin:0;font-weight:normal;font-size:medium}.list address{display:inline;font-style:normal}.list .pr{font-weight:bold}.list .price-cell{font-size:small;text-align:center}.list .icon-cell{text-align:center}.list .icon-cell img{width:60px;height:60px;margin-right:5px;cursor:pointer}.list .icon-cell{width:65px}.list .marker-cell img{width:20px;height:34px;margin:0 2px}.list .store{color:green;font-weight:bold}.list .cluster-selected{background:#efefef}.list .distance{color:#555555}#location{background:white;border:0;border:1px solid #ddd;color:black;margin:0 5px}.tabs td.addr-cell{padding-top:0;padding-bottom:0}.tabs form{display:inline;margin:0}.pr{font-size:medium}.compare a{color:black;text-decoration:none;margin-left:auto;margin-right:auto}h3.name{font-size:medium;font-weight:normal;margin-top:0}.description{width:47em}#panel .description{width:auto}.description td{font-size:small}.description .pr{font-size:medium;font-weight:bold}.list h3{font-size:medium;font-weight:normal;margin:0}.bot td{border-bottom:1px solid #cdcdcd}.list .bot td{padding:5px 10px}.list .description{padding-bottom:0.5em}.currency-input{font-size:90%;font-family:arial,sans-serif;width:3em;text-align:right;vertical-align:middle;margin-top:0.2em}.units-input{font-size:90%;font-family:arial,sans-serif;width:3em;text-align:right;vertical-align:middle;margin-top:0.2em}#q,#addr{-moz-box-sizing:border-box;box-sizing:border-box}#addr{width:16em}#q,#addr{margin-right:.2em}#qt .addr{display:none}#qt.show-addr .addr{display:inline}#qt.show-addr .non-addr{display:none}#qt.show-addr #q{width:11.8em}#qt.show-addr td.addr{display:block;display:table-cell}#qt td{text-align:left;vertical-align:top;white-space:nowrap}#qt span{color:#666}#qt .lbl{font-size:70%}.sw{margin:0 5px 2px 10px;font-size:small}.sort-header td{background:#efefef;vertical-align:middle}.offer-list td{padding:5px 10px;border-bottom:1px solid #cdcdcd}.sort-header .selected{background:#cdcdcd}.disclaimer{font-size:small;margin:0.2em;text-align:center}.n a{text-decoration:none}.n a span{text-decoration:underline} \ No newline at end of file
diff --git a/chrome/test/data/interstitial_page/shopping_files/hp0.gif b/chrome/test/data/interstitial_page/shopping_files/hp0.gif
new file mode 100644
index 0000000..5452545
--- /dev/null
+++ b/chrome/test/data/interstitial_page/shopping_files/hp0.gif
Binary files differ
diff --git a/chrome/test/data/interstitial_page/shopping_files/hp1.gif b/chrome/test/data/interstitial_page/shopping_files/hp1.gif
new file mode 100644
index 0000000..b84be85
--- /dev/null
+++ b/chrome/test/data/interstitial_page/shopping_files/hp1.gif
Binary files differ
diff --git a/chrome/test/data/interstitial_page/shopping_files/hp2.gif b/chrome/test/data/interstitial_page/shopping_files/hp2.gif
new file mode 100644
index 0000000..30623b8
--- /dev/null
+++ b/chrome/test/data/interstitial_page/shopping_files/hp2.gif
Binary files differ
diff --git a/chrome/test/data/interstitial_page/shopping_files/hp3.gif b/chrome/test/data/interstitial_page/shopping_files/hp3.gif
new file mode 100644
index 0000000..ea140b7
--- /dev/null
+++ b/chrome/test/data/interstitial_page/shopping_files/hp3.gif
Binary files differ
diff --git a/chrome/test/data/interstitial_page/x2.gif b/chrome/test/data/interstitial_page/x2.gif
new file mode 100644
index 0000000..552b769
--- /dev/null
+++ b/chrome/test/data/interstitial_page/x2.gif
Binary files differ
diff --git a/chrome/test/data/npapi/arguments.html b/chrome/test/data/npapi/arguments.html
new file mode 100644
index 0000000..835473c
--- /dev/null
+++ b/chrome/test/data/npapi/arguments.html
@@ -0,0 +1,40 @@
+<html>
+
+<head>
+<script src="npapi.js"></script>
+</head>
+
+
+<body>
+<div id="statusPanel" style="border: 1px solid red; width: 100%">
+Test running....
+</div>
+
+
+NPAPI Loading and Argument Tests<p>
+Tests our ability to pass arguments to the plugin via the embed
+tag.<P>
+
+<embed type="application/vnd.npapi-test"
+ src="foo"
+ name="arguments"
+ id="1"
+ mode="np_embed"
+ count="12"
+ size="10"
+ val1="0123456789"
+ val2="01234567890123456789"
+ val3="012345678901234567890123456789"
+ val4="0123456789012345678901234567890123456789"
+ val5="01234567890123456789012345678901234567890123456789"
+ val6="012345678901234567890123456789012345678901234567890123456789"
+ val7="0123456789012345678901234567890123456789012345678901234567890123456789"
+ val8="01234567890123456789012345678901234567890123456789012345678901234567890123456789"
+ val9="012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789"
+ val10="0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789"
+ val11="01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789"
+ val12="012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789"
+>
+
+</body>
+</html>
diff --git a/chrome/test/data/npapi/execute_script_delete_in_npn_evaluate.html b/chrome/test/data/npapi/execute_script_delete_in_npn_evaluate.html
new file mode 100644
index 0000000..f2e2bbe
--- /dev/null
+++ b/chrome/test/data/npapi/execute_script_delete_in_npn_evaluate.html
@@ -0,0 +1,39 @@
+<html>
+
+<head>
+<script src="npapi.js"></script>
+
+<script>
+function DeletePluginWithinScript() {
+ var plugin_div = document.getElementById("PluginDiv");
+ plugin_div.innerHTML = "Object Deleted";
+ onSuccess("npobject_delete_plugin_in_evaluate", 1);
+}
+</script>
+</head>
+
+<body>
+<div id="statusPanel" style="border: 1px solid red; width: 100%">
+Test running....
+</div>
+
+
+NPObject Proxy Test<p>
+
+Tests the case where a plugin instance is deleted in the context
+of NPN_Evaluate
+
+<DIV ID=PluginDiv>
+<embed type="application/vnd.npapi-test"
+ src="foo"
+ name="npobject_delete_plugin_in_evaluate"
+ id="1"
+ mode="np_embed"
+>
+</DIV>
+<script>
+ var height = document.body.offsetHeight;
+</script>
+
+</body>
+</html>
diff --git a/chrome/test/data/npapi/execute_script_delete_in_paint.html b/chrome/test/data/npapi/execute_script_delete_in_paint.html
new file mode 100644
index 0000000..fa9ff21
--- /dev/null
+++ b/chrome/test/data/npapi/execute_script_delete_in_paint.html
@@ -0,0 +1,39 @@
+<html>
+
+<head>
+<script src="npapi.js"></script>
+
+<script>
+function DeletePluginWithinScript() {
+ var plugin_div = document.getElementById("PluginDiv");
+ plugin_div.innerHTML = "Object Deleted";
+ onSuccess("execute_script_delete_in_paint", 1);
+}
+</script>
+</head>
+
+<body>
+<div id="statusPanel" style="border: 1px solid red; width: 100%">
+Test running....
+</div>
+
+
+NPObject Proxy Test<p>
+
+Tests the case where a plugin instance is deleted in the context
+of a synchronous paint.
+
+<DIV ID=PluginDiv>
+<embed type="application/vnd.npapi-test"
+ src="foo"
+ name="execute_script_delete_in_paint"
+ id="1"
+ mode="np_embed"
+>
+</DIV>
+<script>
+ var height = document.body.offsetHeight;
+</script>
+
+</body>
+</html>
diff --git a/chrome/test/data/npapi/get_javascript_url.html b/chrome/test/data/npapi/get_javascript_url.html
new file mode 100644
index 0000000..404613b
--- /dev/null
+++ b/chrome/test/data/npapi/get_javascript_url.html
@@ -0,0 +1,26 @@
+<html>
+
+<head>
+<script src="npapi.js"></script>
+</head>
+
+
+<body>
+<div id="statusPanel" style="border: 1px solid red; width: 100%">
+Test running....
+</div>
+
+
+GetJavscriptURL Test<p>
+This test fetches a javascript URL via the plugin with _top as the
+target frame, and verifies that the call succeeds.
+
+<embed type="application/vnd.npapi-test"
+ src="foo"
+ name="getjavascripturl"
+ id="1"
+ mode="np_embed"
+>
+
+</body>
+</html>
diff --git a/chrome/test/data/npapi/geturl.html b/chrome/test/data/npapi/geturl.html
new file mode 100644
index 0000000..002b63b
--- /dev/null
+++ b/chrome/test/data/npapi/geturl.html
@@ -0,0 +1,26 @@
+<html>
+
+<head>
+<script src="npapi.js"></script>
+</head>
+
+
+<body>
+<div id="statusPanel" style="border: 1px solid red; width: 100%">
+Test running....
+</div>
+
+
+GetURL Test<p>
+This test fetches an URL via the plugin, and verifies that the
+callbacks are expected and that the retrieved content is correct.
+
+<embed type="application/vnd.npapi-test"
+ src="foo"
+ name="geturl"
+ id="1"
+ mode="np_embed"
+>
+
+</body>
+</html>
diff --git a/chrome/test/data/npapi/layout_test_plugin.html b/chrome/test/data/npapi/layout_test_plugin.html
new file mode 100644
index 0000000..d523d3c
--- /dev/null
+++ b/chrome/test/data/npapi/layout_test_plugin.html
@@ -0,0 +1,17 @@
+<html>
+<head>
+<title>Layout Test Plugin Test</title>
+</head>
+<body>
+<embed name="plg" type="application/x-webkit-test-netscape"></embed>
+<script>
+// Test for bug 711411: http://b/issue?id=711411
+// There was a crash because of the plugin dll being unloaded before the JS
+// interpreter got a chance to drop references.
+window.plg.eventLoggingEnabled = true;
+</script>
+
+<!-- Make sure unknown plugin types don't crash either -->
+<embed name="no-plg" type="application/not-installed"></embed>
+</body>
+</html>
diff --git a/chrome/test/data/npapi/many_plugins.html b/chrome/test/data/npapi/many_plugins.html
new file mode 100644
index 0000000..5edcc55
--- /dev/null
+++ b/chrome/test/data/npapi/many_plugins.html
@@ -0,0 +1,94 @@
+<html>
+
+<head>
+<script src="npapi.js"></script>
+</head>
+
+
+<body>
+<div id="statusPanel" style="border: 1px solid red; width: 100%">
+Test running....
+</div>
+
+
+Loading many plugins<p>
+Tests our ability to load multiple plugins in a single page.<P>
+
+<embed type="application/vnd.npapi-test"
+ name="arguments"
+ mode="np_embed"
+ id="1"
+>
+<embed type="application/vnd.npapi-test"
+ name="arguments"
+ mode="np_embed"
+ id="2"
+>
+<embed type="application/vnd.npapi-test"
+ name="arguments"
+ mode="np_embed"
+ id="3"
+>
+<embed type="application/vnd.npapi-test"
+ name="arguments"
+ mode="np_embed"
+ id="4"
+>
+<embed type="application/vnd.npapi-test"
+ name="arguments"
+ mode="np_embed"
+ id="5"
+>
+<embed type="application/vnd.npapi-test"
+ name="arguments"
+ mode="np_embed"
+ id="6"
+>
+<embed type="application/vnd.npapi-test"
+ name="arguments"
+ mode="np_embed"
+ id="7"
+>
+<embed type="application/vnd.npapi-test"
+ name="arguments"
+ mode="np_embed"
+ id="8"
+>
+<embed type="application/vnd.npapi-test"
+ name="arguments"
+ mode="np_embed"
+ id="9"
+>
+<embed type="application/vnd.npapi-test"
+ name="arguments"
+ mode="np_embed"
+ id="10"
+>
+<embed type="application/vnd.npapi-test"
+ name="arguments"
+ mode="np_embed"
+ id="11"
+>
+<embed type="application/vnd.npapi-test"
+ name="arguments"
+ mode="np_embed"
+ id="12"
+>
+<embed type="application/vnd.npapi-test"
+ name="arguments"
+ mode="np_embed"
+ id="13"
+>
+<embed type="application/vnd.npapi-test"
+ name="arguments"
+ mode="np_embed"
+ id="14"
+>
+<embed type="application/vnd.npapi-test"
+ name="arguments"
+ mode="np_embed"
+ id="15"
+>
+
+</body>
+</html>
diff --git a/chrome/test/data/npapi/new_fails.html b/chrome/test/data/npapi/new_fails.html
new file mode 100644
index 0000000..a4b7de9
--- /dev/null
+++ b/chrome/test/data/npapi/new_fails.html
@@ -0,0 +1,30 @@
+<html>
+
+<head>
+<script src="npapi.js"></script>
+</head>
+
+
+<body>
+<div id="statusPanel" style="border: 1px solid red; width: 100%">
+Test running....
+</div>
+
+
+NPP_NEW test<p>
+This test ensures we don't crash or assert if NPP_New fails.
+
+<embed type="application/vnd.npapi-test"
+ src="foo"
+ name="new_fails"
+ id="1"
+ mode="np_embed"
+>
+
+<script>
+ var height = document.body.offsetHeight;
+ onSuccess("new_fails", 1);
+</script>
+
+</body>
+</html>
diff --git a/chrome/test/data/npapi/npapi.js b/chrome/test/data/npapi/npapi.js
new file mode 100644
index 0000000..207d188
--- /dev/null
+++ b/chrome/test/data/npapi/npapi.js
@@ -0,0 +1,28 @@
+//
+// This script provides some mechanics for testing NPAPI
+//
+
+/* public */ function onSuccess(name, id)
+{
+ setTimeout(onFinished, 0, name, id, "OK");
+}
+
+/* public */ function onFailure(name, id, status)
+{
+ setTimeout(onFinished, 0, name, id, status);
+}
+
+
+
+// Finish running a test by setting the status
+// and the cookie.
+/* private */ function onFinished(name, id, result)
+{
+ var statusPanel = document.getElementById("statusPanel");
+ if (statusPanel) {
+ statusPanel.innerHTML = result;
+ }
+
+ var cookie = name + "." + id + ".status=" + result + "; path=/";
+ document.cookie = cookie;
+}
diff --git a/chrome/test/data/npapi/npobject_lifetime_test.html b/chrome/test/data/npapi/npobject_lifetime_test.html
new file mode 100644
index 0000000..634fad8
--- /dev/null
+++ b/chrome/test/data/npapi/npobject_lifetime_test.html
@@ -0,0 +1,58 @@
+<html>
+
+<head>
+<script src="npapi.js"></script>
+</head>
+
+
+<body>
+<div id="statusPanel" style="border: 1px solid red; width: 100%">
+Test running....
+</div>
+
+
+NPObject Lifetime test<p>
+
+Tests the case where a plugin holds on to an NPObject reference
+to another plugin in a different frame in the page and whether
+the npobject is callable when the frame is destroyed.
+
+<div ID=npobject_lifetime_test_instance2>
+<iframe src="npobject_lifetime_test_second_instance.html" name="plugin_frame">
+</iframe>
+</div>
+
+<embed type="application/vnd.npapi-test"
+ src="foo"
+ name="npobject_lifetime_test"
+ id="1"
+ mode="np_embed">
+
+<script>
+
+function GetSecondPluginInstance() {
+ var plugin_frame = window.frames["plugin_frame"];
+ if (!plugin_frame) {
+ alert("failed to find frame in frames list");
+ return;
+ }
+
+ var plugin = plugin_frame.document.getElementById(2);
+ if (!plugin) {
+ alert("Failed to locate second plugin");
+ return;
+ }
+ return plugin;
+}
+
+function DeleteSecondPluginInstance() {
+ var frame_div = document.getElementById("npobject_lifetime_test_instance2");
+ if (frame_div.parentNode && frame_div.parentNode.removeChild) {
+ frame_div.parentNode.removeChild(frame_div);
+ }
+}
+</script>
+
+</body>
+</html>
+
diff --git a/chrome/test/data/npapi/npobject_lifetime_test_second_instance.html b/chrome/test/data/npapi/npobject_lifetime_test_second_instance.html
new file mode 100644
index 0000000..5876f8e
--- /dev/null
+++ b/chrome/test/data/npapi/npobject_lifetime_test_second_instance.html
@@ -0,0 +1,20 @@
+<html>
+
+<body>
+<div id="statusPanel" style="border: 1px solid red; width: 100%">
+Second instance.
+</div>
+
+NPObject Lifetime test second plugin instance<p>
+
+Tests the case where a plugin holds on to an NPObject reference
+to another plugin in a different frame in the page and whether
+the npobject is callable when the frame is destroyed.
+
+<embed type="application/vnd.npapi-test"
+ name="npobject_lifetime_test_second_instance"
+ id="2"
+ mode="np_embed"> </embed>
+
+</body>
+</html>
diff --git a/chrome/test/data/npapi/npobject_proxy.html b/chrome/test/data/npapi/npobject_proxy.html
new file mode 100644
index 0000000..ef85ee7
--- /dev/null
+++ b/chrome/test/data/npapi/npobject_proxy.html
@@ -0,0 +1,28 @@
+<html>
+
+<head>
+<script src="npapi.js"></script>
+</head>
+
+
+<body>
+<div id="statusPanel" style="border: 1px solid red; width: 100%">
+Test running....
+</div>
+
+
+NPObject Proxy Test<p>
+
+Tests that if an NPObject is proxies back to its original process, the
+original pointer is returned and not a proxy. If this fails the plugin
+will crash.
+
+<embed type="application/vnd.npapi-test"
+ src="foo"
+ name="npobject_proxy"
+ id="1"
+ mode="np_embed"
+>
+
+</body>
+</html>
diff --git a/chrome/test/data/npapi/self_delete_plugin_geturl.html b/chrome/test/data/npapi/self_delete_plugin_geturl.html
new file mode 100644
index 0000000..2d14340
--- /dev/null
+++ b/chrome/test/data/npapi/self_delete_plugin_geturl.html
@@ -0,0 +1,37 @@
+<html>
+<head>
+<title>Self Deleting Plugin Test - GetURL</title>
+<script src="npapi.js"></script>
+<script>
+function DeletePluginWithinScript() {
+ var plugin_div = document.getElementById("PluginDiv");
+ plugin_div.innerHTML = "Object Deleted";
+}
+
+function CallGetUrl() {
+ var plg = window.document["plg"];
+ plg.getURL("javascript:DeletePluginWithinScript()");
+}
+</script>
+</head>
+
+<body>
+
+<h2>Test to delete a plugin during script execution</h2>
+
+<p>
+This test is for a corner case when a plugin executes a script
+that deletes the invoking plugin itself.
+</p>
+
+<DIV ID=PluginDiv>
+<embed name="plg" type="application/x-webkit-test-netscape"></embed>
+</DIV>
+<script>
+ CallGetUrl();
+ onSuccess("self_delete_plugin_geturl", 1);
+</script>
+
+</body>
+</html>
+
diff --git a/chrome/test/data/npapi/self_delete_plugin_invoke.html b/chrome/test/data/npapi/self_delete_plugin_invoke.html
new file mode 100644
index 0000000..73b940f
--- /dev/null
+++ b/chrome/test/data/npapi/self_delete_plugin_invoke.html
@@ -0,0 +1,33 @@
+<html>
+<head>
+<title>Self Deleting Plugin Test - Invoke</title>
+<script src="npapi.js"></script>
+<script>
+function DeletePluginWithinScript() {
+ var plugin_div = document.getElementById("PluginDiv");
+ plugin_div.innerHTML = "Object Deleted";
+}
+</script>
+</head>
+
+<body>
+
+<h2>Test to delete a plugin during script execution</h2>
+
+<p>
+This test is for a corner case when a plugin executes a script
+that deletes the invoking plugin itself.
+</p>
+
+<DIV ID=PluginDiv>
+<embed name="plg" type="application/x-webkit-test-netscape"></embed>
+</DIV>
+<script>
+ var plg = window.document["plg"];
+ plg.testCallback("DeletePluginWithinScript");
+ onSuccess("self_delete_plugin_invoke", 1);
+</script>
+
+</body>
+</html>
+
diff --git a/chrome/test/data/npapi/self_delete_plugin_stream.html b/chrome/test/data/npapi/self_delete_plugin_stream.html
new file mode 100644
index 0000000..a43c38a
--- /dev/null
+++ b/chrome/test/data/npapi/self_delete_plugin_stream.html
@@ -0,0 +1,34 @@
+<html>
+
+<head>
+<script src="npapi.js"></script>
+
+<script>
+function DeletePluginWithinScript() {
+ var plugin_div = document.getElementById("PluginDiv");
+ plugin_div.innerHTML = "Object Deleted";
+ onSuccess("self_delete_plugin_stream", 1);
+}
+</script>
+</head>
+
+<body>
+<div id="statusPanel" style="border: 1px solid red; width: 100%">
+Test running....
+</div>
+
+
+<DIV ID=PluginDiv>
+<embed type="application/vnd.npapi-test"
+ src="foo"
+ name="self_delete_plugin_stream"
+ id="1"
+ mode="np_embed"
+>
+</DIV>
+<script>
+ var height = document.body.offsetHeight;
+</script>
+
+</body>
+</html>
diff --git a/chrome/test/data/npapi/verify_plugin_window_rect.html b/chrome/test/data/npapi/verify_plugin_window_rect.html
new file mode 100644
index 0000000..7dca47a
--- /dev/null
+++ b/chrome/test/data/npapi/verify_plugin_window_rect.html
@@ -0,0 +1,30 @@
+<html>
+
+<head>
+<script src="npapi.js"></script>
+</head>
+
+<body>
+<div id="statusPanel" style="border: 1px solid red; width: 100%">
+Test running....
+</div>
+
+
+Plugin Window Rect Test<p>
+
+Tests whether the plugin window has a non zero client rect.
+
+<DIV ID=PluginDiv>
+<embed type="application/vnd.npapi-test"
+ src="foo"
+ name="checkwindowrect"
+ id="1"
+ mode="np_embed"
+>
+</DIV>
+<script>
+ var height = document.body.offsetHeight;
+</script>
+
+</body>
+</html>
diff --git a/chrome/test/data/omnibox_tests.xml b/chrome/test/data/omnibox_tests.xml
new file mode 100644
index 0000000..f9ce9521
--- /dev/null
+++ b/chrome/test/data/omnibox_tests.xml
@@ -0,0 +1,38 @@
+<omnibox_tests>
+ <test query="google.com">
+ </test>
+ <test query="www.yahoo.com">
+ </test>
+ <test query="http://myspace.com/">
+ </test>
+ <test query="youtube.com">
+ </test>
+ <test query="wikipedia.org/">
+ </test>
+ <test query="msn.com">
+ </test>
+ <test query="ebay.com">
+ </test>
+ <test query="http://live.com">
+ </test>
+ <test query="craigslist.org">
+ </test>
+ <test query="http://blogger.com/">
+ </test>
+ <test query="flickr.com">
+ </test>
+ <test query="nytimes.com">
+ </test>
+ <test query="cnn.com/">
+ </test>
+ <test query="digg.com">
+ </test>
+ <test query="rapidshare.com">
+ </test>
+ <test query="orkut.com/">
+ </test>
+ <test query="http://download.com">
+ </test>
+ <test query="photobucket.com/">
+ </test>
+</omnibox_tests>
diff --git a/chrome/test/data/onunload_cookie.html b/chrome/test/data/onunload_cookie.html
new file mode 100644
index 0000000..0a7de8d
--- /dev/null
+++ b/chrome/test/data/onunload_cookie.html
@@ -0,0 +1,18 @@
+<html>
+ <head>
+ <title>Loading...</title>
+ </head>
+ <body onload="attachUnloadListener()">
+ <script>
+ function attachUnloadListener() {
+ window.addEventListener('unload', onUnload, false);
+ document.title = "set cookie on unload";
+ }
+
+ function onUnload() {
+ document.cookie = "onunloadCookie=foo";
+ }
+ </script>
+ <p>Navigate to another page to set cookie</p>
+ </body>
+</html>
diff --git a/chrome/test/data/pref_service/overlay.json b/chrome/test/data/pref_service/overlay.json
new file mode 100644
index 0000000..ea4d831
--- /dev/null
+++ b/chrome/test/data/pref_service/overlay.json
@@ -0,0 +1,22 @@
+{
+ "both": {
+ "bool": false,
+ "dictionary": {
+ "value": "persistent"
+ },
+ "int": 1,
+ "list": [ "persistent" ],
+ "real": 1,
+ "string": "persistent"
+ },
+ "persistent": {
+ "bool": false,
+ "dictionary": {
+ "value": "persistent"
+ },
+ "int": 1,
+ "list": [ "persistent" ],
+ "real": 1.0,
+ "string": "persistent"
+ }
+}
diff --git a/chrome/test/data/pref_service/read.json b/chrome/test/data/pref_service/read.json
new file mode 100644
index 0000000..0225f17
--- /dev/null
+++ b/chrome/test/data/pref_service/read.json
@@ -0,0 +1,7 @@
+{
+ "homepage": "http://www.cnn.com",
+ "tabs": {
+ "new_windows_in_tabs": true,
+ "max_tabs": 20
+ }
+} \ No newline at end of file
diff --git a/chrome/test/data/pref_service/write.golden.json b/chrome/test/data/pref_service/write.golden.json
new file mode 100644
index 0000000..1da3ec4
--- /dev/null
+++ b/chrome/test/data/pref_service/write.golden.json
@@ -0,0 +1,7 @@
+{
+ "homepage": "http://www.cnn.com",
+ "tabs": {
+ "max_tabs": 10,
+ "new_windows_in_tabs": false
+ }
+}
diff --git a/chrome/test/data/printing/alert_small.png b/chrome/test/data/printing/alert_small.png
new file mode 100644
index 0000000..6ac7854
--- /dev/null
+++ b/chrome/test/data/printing/alert_small.png
Binary files differ
diff --git a/chrome/test/data/printing/cleardot.gif b/chrome/test/data/printing/cleardot.gif
new file mode 100644
index 0000000..1d11fa9
--- /dev/null
+++ b/chrome/test/data/printing/cleardot.gif
Binary files differ
diff --git a/chrome/test/data/printing/click_me.png b/chrome/test/data/printing/click_me.png
new file mode 100644
index 0000000..fc2a70b
--- /dev/null
+++ b/chrome/test/data/printing/click_me.png
Binary files differ
diff --git a/chrome/test/data/printing/iframe.emf b/chrome/test/data/printing/iframe.emf
new file mode 100644
index 0000000..dc7839b
--- /dev/null
+++ b/chrome/test/data/printing/iframe.emf
Binary files differ
diff --git a/chrome/test/data/printing/iframe.htm b/chrome/test/data/printing/iframe.htm
new file mode 100644
index 0000000..7c9f443
--- /dev/null
+++ b/chrome/test/data/printing/iframe.htm
@@ -0,0 +1,29 @@
+<html>
+<title>iframe</title>
+<SCRIPT type="text/javascript" language="JavaScript">
+function PrintIframe() {
+ // Standard way
+ //window.frames["inner_frame"].focus();
+ //window.frames["inner_frame"].print();
+ // IE6 way
+ //document.inner_frame.focus();
+ //document.inner_frame.print();
+ // IE7 way. That's the way Safari does it.
+ window.frames["inner_frame"].document.execCommand('print',false,null)
+}
+function DelayedPrint() {
+ setTimeout(PrintIframe, 0);
+}
+</SCRIPT>
+<body onload="javascript:DelayedPrint()">
+
+<p>
+<a href="javascript:PrintIframe()"><img src="click_me.png" /></a>
+<p>
+<div>
+<iframe src="test2.html" id="inner_frame" style="height:150px; margin:0px; padding:0px"><html><body>A</body></html></iframe>
+</div>
+<br>
+<img src="sadtab.png" />
+</body>
+</html>
diff --git a/chrome/test/data/printing/iframe.png b/chrome/test/data/printing/iframe.png
new file mode 100644
index 0000000..f57d335
--- /dev/null
+++ b/chrome/test/data/printing/iframe.png
Binary files differ
diff --git a/chrome/test/data/printing/popup_delayed_print.emf b/chrome/test/data/printing/popup_delayed_print.emf
new file mode 100644
index 0000000..0698293
--- /dev/null
+++ b/chrome/test/data/printing/popup_delayed_print.emf
Binary files differ
diff --git a/chrome/test/data/printing/popup_delayed_print.htm b/chrome/test/data/printing/popup_delayed_print.htm
new file mode 100644
index 0000000..bddcb20
--- /dev/null
+++ b/chrome/test/data/printing/popup_delayed_print.htm
@@ -0,0 +1,13 @@
+<HTML>
+<HEAD>
+<TITLE>Bug 1184673</TITLE>
+</HEAD>
+<script>
+function DoThePopup() {
+ window.open('popup_delayed_print_child.htm');
+}
+</script>
+<BODY onload="javascript:DoThePopup()">
+<a href="javascript:DoThePopup()">This won't be printed.</a>
+</BODY>
+</HTML> \ No newline at end of file
diff --git a/chrome/test/data/printing/popup_delayed_print.png b/chrome/test/data/printing/popup_delayed_print.png
new file mode 100644
index 0000000..34fa01c
--- /dev/null
+++ b/chrome/test/data/printing/popup_delayed_print.png
Binary files differ
diff --git a/chrome/test/data/printing/popup_delayed_print_child.htm b/chrome/test/data/printing/popup_delayed_print_child.htm
new file mode 100644
index 0000000..7463b9d
--- /dev/null
+++ b/chrome/test/data/printing/popup_delayed_print_child.htm
@@ -0,0 +1,14 @@
+<HTML>
+<HEAD>
+<TITLE>Bug 1184673</TITLE>
+</HEAD>
+<script>
+function DoThePrint() {
+ window.print();
+ window.close();
+}
+</script>
+<BODY onload="DoThePrint()">
+<img src="click_me.png" />
+</BODY>
+</HTML> \ No newline at end of file
diff --git a/chrome/test/data/printing/sadtab.png b/chrome/test/data/printing/sadtab.png
new file mode 100644
index 0000000..a19d09d
--- /dev/null
+++ b/chrome/test/data/printing/sadtab.png
Binary files differ
diff --git a/chrome/test/data/printing/test1.emf b/chrome/test/data/printing/test1.emf
new file mode 100644
index 0000000..3f102e6
--- /dev/null
+++ b/chrome/test/data/printing/test1.emf
Binary files differ
diff --git a/chrome/test/data/printing/test1.html b/chrome/test/data/printing/test1.html
new file mode 100644
index 0000000..af4db0f
--- /dev/null
+++ b/chrome/test/data/printing/test1.html
@@ -0,0 +1,20 @@
+<html>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<title>test1</title>
+<body bgcolor=#eeeeee >
+<a href="">Random invalid link.</a>
+<br>
+<div style="font-family:arial unicode ms">
+Arabic ligature testing: allāh: ﷲ‎
+<br>
+Arabic ligature testing: lām: الله
+<br>
+Alphabet in Hebrew: alephbet: אלפבית
+<br>
+Hello world in Korean: 여러분, 안녕하세요
+<br>
+Hello world in Chinese: 你好世界
+<br>
+</div>
+</body>
+</html> \ No newline at end of file
diff --git a/chrome/test/data/printing/test1.png b/chrome/test/data/printing/test1.png
new file mode 100644
index 0000000..423d640
--- /dev/null
+++ b/chrome/test/data/printing/test1.png
Binary files differ
diff --git a/chrome/test/data/printing/test1_cleartype.png b/chrome/test/data/printing/test1_cleartype.png
new file mode 100644
index 0000000..99feff7
--- /dev/null
+++ b/chrome/test/data/printing/test1_cleartype.png
Binary files differ
diff --git a/chrome/test/data/printing/test2.emf b/chrome/test/data/printing/test2.emf
new file mode 100644
index 0000000..6ccfa9e
--- /dev/null
+++ b/chrome/test/data/printing/test2.emf
Binary files differ
diff --git a/chrome/test/data/printing/test2.html b/chrome/test/data/printing/test2.html
new file mode 100644
index 0000000..aa9ec22
--- /dev/null
+++ b/chrome/test/data/printing/test2.html
@@ -0,0 +1,10 @@
+<html>
+<title>test2</title>
+<body bgcolor=#eeeeee >
+<img src="sadtab.png" width=10 height=10 />
+<br>
+<img src="sadtab.png" />
+<br>
+<img src="sadtab.png" width=100 height=100 />
+</body>
+</html>
diff --git a/chrome/test/data/printing/test2.png b/chrome/test/data/printing/test2.png
new file mode 100644
index 0000000..f57d335
--- /dev/null
+++ b/chrome/test/data/printing/test2.png
Binary files differ
diff --git a/chrome/test/data/printing/test3.emf b/chrome/test/data/printing/test3.emf
new file mode 100644
index 0000000..ec5fbc7
--- /dev/null
+++ b/chrome/test/data/printing/test3.emf
Binary files differ
diff --git a/chrome/test/data/printing/test3.html b/chrome/test/data/printing/test3.html
new file mode 100644
index 0000000..06f34c7
--- /dev/null
+++ b/chrome/test/data/printing/test3.html
@@ -0,0 +1,8 @@
+<html>
+<title>test3</title>
+<body bgcolor=#eeeeee >
+<img src="cleardot.gif" />
+<br>
+<img src="cleardot.gif" width=10 height=10 />
+</body>
+</html>
diff --git a/chrome/test/data/printing/test3.png b/chrome/test/data/printing/test3.png
new file mode 100644
index 0000000..d1a4948
--- /dev/null
+++ b/chrome/test/data/printing/test3.png
Binary files differ
diff --git a/chrome/test/data/printing/test4.emf b/chrome/test/data/printing/test4.emf
new file mode 100644
index 0000000..3a62454
--- /dev/null
+++ b/chrome/test/data/printing/test4.emf
Binary files differ
diff --git a/chrome/test/data/printing/test4.html b/chrome/test/data/printing/test4.html
new file mode 100644
index 0000000..ae12955
--- /dev/null
+++ b/chrome/test/data/printing/test4.html
@@ -0,0 +1,10 @@
+<html>
+<title>test4</title>
+<body bgcolor=#eeeeee >
+<img src="alert_small.png" width=10 height=10 />
+<br>
+<img src="alert_small.png" />
+<br>
+<img src="alert_small.png" width=100 height=100 />
+</body>
+</html>
diff --git a/chrome/test/data/printing/test4.png b/chrome/test/data/printing/test4.png
new file mode 100644
index 0000000..68f9551
--- /dev/null
+++ b/chrome/test/data/printing/test4.png
Binary files differ
diff --git a/chrome/test/data/printing/test5.emf b/chrome/test/data/printing/test5.emf
new file mode 100644
index 0000000..a6a1a48
--- /dev/null
+++ b/chrome/test/data/printing/test5.emf
Binary files differ
diff --git a/chrome/test/data/printing/test5.html b/chrome/test/data/printing/test5.html
new file mode 100644
index 0000000..e1b09dc
--- /dev/null
+++ b/chrome/test/data/printing/test5.html
@@ -0,0 +1,18 @@
+<html>
+<title>test5</title>
+<style>
+#localbackground img {
+background:white url(sadtab.png) no-repeat scroll 0px;
+height:66px;
+width:66px;
+}
+img {
+border:medium none;
+}
+</style>
+<body>
+<div id="localbackground">
+<img src="cleardot.gif" width="66" height="66" border="0" alt="">
+</div>
+</body>
+</html> \ No newline at end of file
diff --git a/chrome/test/data/printing/test5.png b/chrome/test/data/printing/test5.png
new file mode 100644
index 0000000..2ef0a17
--- /dev/null
+++ b/chrome/test/data/printing/test5.png
Binary files differ
diff --git a/chrome/test/data/profiles/chrome_prefs/History b/chrome/test/data/profiles/chrome_prefs/History
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/chrome/test/data/profiles/chrome_prefs/History
diff --git a/chrome/test/data/profiles/chrome_prefs/Preferences b/chrome/test/data/profiles/chrome_prefs/Preferences
new file mode 100644
index 0000000..937b1e39
--- /dev/null
+++ b/chrome/test/data/profiles/chrome_prefs/Preferences
@@ -0,0 +1,15 @@
+{
+ "intl": {
+ "charset_default": "utf8"
+ },
+ "webkit": {
+ "webprefs": {
+ "default_font_size": 20,
+ "text_areas_are_resizable": false,
+ "uses_universal_detector": true,
+
+ "foo": "bar",
+ "standard_font_family": true
+ }
+ }
+}
diff --git a/chrome/test/data/profiles/sample/Full Text Index b/chrome/test/data/profiles/sample/Full Text Index
new file mode 100644
index 0000000..b1f52bd
--- /dev/null
+++ b/chrome/test/data/profiles/sample/Full Text Index
Binary files differ
diff --git a/chrome/test/data/profiles/sample/History b/chrome/test/data/profiles/sample/History
new file mode 100644
index 0000000..517a3a5
--- /dev/null
+++ b/chrome/test/data/profiles/sample/History
Binary files differ
diff --git a/chrome/test/data/profiles/sample/Preferences b/chrome/test/data/profiles/sample/Preferences
new file mode 100644
index 0000000..19765bd
--- /dev/null
+++ b/chrome/test/data/profiles/sample/Preferences
@@ -0,0 +1 @@
+null
diff --git a/chrome/test/data/profiles/sample/Thumbnails b/chrome/test/data/profiles/sample/Thumbnails
new file mode 100644
index 0000000..404701d
--- /dev/null
+++ b/chrome/test/data/profiles/sample/Thumbnails
Binary files differ
diff --git a/chrome/test/data/profiles/sample/Visited Links b/chrome/test/data/profiles/sample/Visited Links
new file mode 100644
index 0000000..48635f9
--- /dev/null
+++ b/chrome/test/data/profiles/sample/Visited Links
Binary files differ
diff --git a/chrome/test/data/profiles/sample/Web Data b/chrome/test/data/profiles/sample/Web Data
new file mode 100644
index 0000000..0954bf2
--- /dev/null
+++ b/chrome/test/data/profiles/sample/Web Data
Binary files differ
diff --git a/chrome/test/data/profiles/typical_history/Default/Cookies b/chrome/test/data/profiles/typical_history/Default/Cookies
new file mode 100644
index 0000000..e138f7c
--- /dev/null
+++ b/chrome/test/data/profiles/typical_history/Default/Cookies
Binary files differ
diff --git a/chrome/test/data/profiles/typical_history/Default/Full Text Index b/chrome/test/data/profiles/typical_history/Default/Full Text Index
new file mode 100644
index 0000000..65ea2f6
--- /dev/null
+++ b/chrome/test/data/profiles/typical_history/Default/Full Text Index
Binary files differ
diff --git a/chrome/test/data/profiles/typical_history/Default/History b/chrome/test/data/profiles/typical_history/Default/History
new file mode 100644
index 0000000..9c33937
--- /dev/null
+++ b/chrome/test/data/profiles/typical_history/Default/History
Binary files differ
diff --git a/chrome/test/data/profiles/typical_history/Default/Preferences b/chrome/test/data/profiles/typical_history/Default/Preferences
new file mode 100644
index 0000000..e56c782
--- /dev/null
+++ b/chrome/test/data/profiles/typical_history/Default/Preferences
@@ -0,0 +1,11 @@
+{
+ "profile": {
+ "exited_cleanly": true,
+ "id": "not-signed-in",
+ "name": "Not Signed In",
+ "nickname": "not-signed-in"
+ },
+ "spellcheck": {
+ "dictionary": "en-US"
+ }
+}
diff --git a/chrome/test/data/profiles/typical_history/Default/Thumbnails b/chrome/test/data/profiles/typical_history/Default/Thumbnails
new file mode 100644
index 0000000..fc26118
--- /dev/null
+++ b/chrome/test/data/profiles/typical_history/Default/Thumbnails
Binary files differ
diff --git a/chrome/test/data/profiles/typical_history/Default/Visited Links b/chrome/test/data/profiles/typical_history/Default/Visited Links
new file mode 100644
index 0000000..2fa35a9
--- /dev/null
+++ b/chrome/test/data/profiles/typical_history/Default/Visited Links
Binary files differ
diff --git a/chrome/test/data/profiles/typical_history/README.txt b/chrome/test/data/profiles/typical_history/README.txt
new file mode 100644
index 0000000..d8441f9
--- /dev/null
+++ b/chrome/test/data/profiles/typical_history/README.txt
@@ -0,0 +1,14 @@
+This directory is supposed to represent a "typical" size of a history database
+that a user will have. It does not include thumbnail or full text index data.
+It should be copied to another location before using in a test.
+
+It was generated with
+ <delete the files "Full Text Index" and "History" in "Default" - this is important!>
+ generate_profile --history-only 50000 "Default"
+
+The unit test HistoryProfileTest.TypicalProfileVersion tests that the version
+of this profile is the same that the application is expecting without
+migration. Otherwise, migration time will be counted in some of the performance
+tests.
+
+
diff --git a/chrome/test/data/profiles/window_placement/Local State b/chrome/test/data/profiles/window_placement/Local State
new file mode 100644
index 0000000..39bc7d5
--- /dev/null
+++ b/chrome/test/data/profiles/window_placement/Local State
@@ -0,0 +1,11 @@
+{
+ "browser" : {
+ "window_placement" : {
+ "bottom" : 610,
+ "left" : 50,
+ "maximized" : false,
+ "right" : 1014,
+ "top" : 50
+ }
+ }
+}
diff --git a/chrome/test/data/purify/ignore.txt b/chrome/test/data/purify/ignore.txt
new file mode 100644
index 0000000..1f9a186
--- /dev/null
+++ b/chrome/test/data/purify/ignore.txt
@@ -0,0 +1,6 @@
+# See bug 1157381
+Pure: Trap bits found in live chunk
+
+# See bug 1128489
+NSSDecryptor::Init
+NSSDecryptor::Free
diff --git a/chrome/test/data/purify/ipc_tests.exe_MLK.txt b/chrome/test/data/purify/ipc_tests.exe_MLK.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/chrome/test/data/purify/ipc_tests.exe_MLK.txt
diff --git a/chrome/test/data/purify/ipc_tests.exe_UMR.txt b/chrome/test/data/purify/ipc_tests.exe_UMR.txt
new file mode 100644
index 0000000..6f7d34f
--- /dev/null
+++ b/chrome/test/data/purify/ipc_tests.exe_UMR.txt
@@ -0,0 +1,157 @@
+Uninitialized memory read in strlen
+Error Location
+ ...
+ chrome/common/ipc_tests.cc Send
+ chrome/common/ipc_tests.cc MyChannelListener::OnMessageReceived(Message::IPC const&)
+ chrome/common/ipc_channel.cc IPC::Channel::ProcessIncomingMessages(void)
+ chrome/common/ipc_channel.cc IPC::Channel::OnObjectSignaled(void *)
+ base/message_loop.cc MessageLoop::SignalWatcher(DWORD)
+ base/message_loop.cc MessageLoop::ProcessNextObject(void)
+ base/message_loop.cc MessageLoop::Run(Dispatcher::MessageLoop *)
+ base/message_loop.cc MessageLoop::Run(void)
+ chrome/common/ipc_tests.cc RunTestClient
+ chrome/common/ipc_tests.cc main
+ ...
+
+Uninitialized memory read in WriteFile
+Error Location
+ ...
+ chrome/common/ipc_channel.cc IPC::Channel::ProcessOutgoingMessages(void)
+ chrome/common/ipc_channel.cc IPC::Channel::OnObjectSignaled(void *)
+ chrome/common/ipc_channel.cc IPC::Channel::Send(Message::IPC *)
+ chrome/common/ipc_tests.cc Send
+ chrome/common/ipc_tests.cc MyChannelListener::OnMessageReceived(Message::IPC const&)
+ chrome/common/ipc_channel.cc IPC::Channel::ProcessIncomingMessages(void)
+ chrome/common/ipc_channel.cc IPC::Channel::OnObjectSignaled(void *)
+ base/message_loop.cc MessageLoop::SignalWatcher(DWORD)
+ base/message_loop.cc MessageLoop::ProcessNextObject(void)
+ base/message_loop.cc MessageLoop::Run(Dispatcher::MessageLoop *)
+ base/message_loop.cc MessageLoop::Run(void)
+ chrome/common/ipc_tests.cc RunTestClient
+ chrome/common/ipc_tests.cc main
+ ...
+Alloc Location
+ ...
+ base/pickle.cc Pickle::Resize(UINT)
+ base/pickle.cc Pickle::BeginWrite(UINT)
+ base/pickle.cc Pickle::WriteBytes(void const*,int)
+ base/pickle.cc Pickle::WriteString(basic_string::std const&)
+ chrome/common/ipc_tests.cc Send
+ chrome/common/ipc_tests.cc MyChannelListener::OnMessageReceived(Message::IPC const&)
+ chrome/common/ipc_channel.cc IPC::Channel::ProcessIncomingMessages(void)
+ chrome/common/ipc_channel.cc IPC::Channel::OnObjectSignaled(void *)
+ base/message_loop.cc MessageLoop::SignalWatcher(DWORD)
+ base/message_loop.cc MessageLoop::ProcessNextObject(void)
+ base/message_loop.cc MessageLoop::Run(Dispatcher::MessageLoop *)
+ base/message_loop.cc MessageLoop::Run(void)
+ chrome/common/ipc_tests.cc RunTestClient
+ chrome/common/ipc_tests.cc main
+ ...
+
+Uninitialized memory read in strlen
+Error Location
+ ...
+ chrome/common/ipc_tests.cc Send
+ chrome/common/ipc_tests.cc MyChannelListener::OnMessageReceived(Message::IPC const&)
+ chrome/common/ipc_channel.cc IPC::Channel::ProcessIncomingMessages(void)
+ chrome/common/ipc_channel.cc IPC::Channel::OnObjectSignaled(void *)
+ base/message_loop.cc MessageLoop::SignalWatcher(DWORD)
+ base/message_loop.cc MessageLoop::Run(Dispatcher::MessageLoop *)
+ base/message_loop.cc MessageLoop::Run(void)
+ chrome/common/ipc_tests.cc RunTestClient
+ chrome/common/ipc_tests.cc main
+ ...
+
+Uninitialized memory read in WriteFile
+Error Location
+ ...
+ chrome/common/ipc_channel.cc IPC::Channel::ProcessOutgoingMessages(void)
+ chrome/common/ipc_channel.cc IPC::Channel::OnObjectSignaled(void *)
+ chrome/common/ipc_channel.cc IPC::Channel::Send(Message::IPC *)
+ chrome/common/ipc_tests.cc Send
+ chrome/common/ipc_tests.cc MyChannelListener::OnMessageReceived(Message::IPC const&)
+ chrome/common/ipc_channel.cc IPC::Channel::ProcessIncomingMessages(void)
+ chrome/common/ipc_channel.cc IPC::Channel::OnObjectSignaled(void *)
+ base/message_loop.cc MessageLoop::SignalWatcher(DWORD)
+ base/message_loop.cc MessageLoop::Run(Dispatcher::MessageLoop *)
+ base/message_loop.cc MessageLoop::Run(void)
+ chrome/common/ipc_tests.cc RunTestClient
+ chrome/common/ipc_tests.cc main
+ ...
+Alloc Location
+ ...
+ base/pickle.cc Pickle::Resize(UINT)
+ base/pickle.cc Pickle::BeginWrite(UINT)
+ base/pickle.cc Pickle::WriteBytes(void const*,int)
+ base/pickle.cc Pickle::WriteString(basic_string::std const&)
+ chrome/common/ipc_tests.cc Send
+ chrome/common/ipc_tests.cc MyChannelListener::OnMessageReceived(Message::IPC const&)
+ chrome/common/ipc_channel.cc IPC::Channel::ProcessIncomingMessages(void)
+ chrome/common/ipc_channel.cc IPC::Channel::OnObjectSignaled(void *)
+ base/message_loop.cc MessageLoop::SignalWatcher(DWORD)
+ base/message_loop.cc MessageLoop::Run(Dispatcher::MessageLoop *)
+ base/message_loop.cc MessageLoop::Run(void)
+ chrome/common/ipc_tests.cc RunTestClient
+ chrome/common/ipc_tests.cc main
+ ...
+
+Uninitialized memory read in WriteFile
+Error Location
+ ...
+ chrome/common/ipc_channel.cc IPC::Channel::ProcessOutgoingMessages(void)
+ chrome/common/ipc_channel.cc IPC::Channel::Send(Message::IPC *)
+ chrome/common/ipc_tests.cc Send
+ chrome/common/ipc_tests.cc MyChannelListener::OnMessageReceived(Message::IPC const&)
+ chrome/common/ipc_channel.cc IPC::Channel::ProcessIncomingMessages(void)
+ chrome/common/ipc_channel.cc IPC::Channel::OnObjectSignaled(void *)
+ base/message_loop.cc MessageLoop::SignalWatcher(DWORD)
+ base/message_loop.cc MessageLoop::Run(Dispatcher::MessageLoop *)
+ base/message_loop.cc MessageLoop::Run(void)
+ chrome/common/ipc_tests.cc RunTestClient
+ chrome/common/ipc_tests.cc main
+ ...
+Alloc Location
+ ...
+ base/pickle.cc Pickle::Resize(UINT)
+ base/pickle.cc Pickle::BeginWrite(UINT)
+ base/pickle.cc Pickle::WriteBytes(void const*,int)
+ base/pickle.cc Pickle::WriteString(basic_string::std const&)
+ chrome/common/ipc_tests.cc Send
+ chrome/common/ipc_tests.cc MyChannelListener::OnMessageReceived(Message::IPC const&)
+ chrome/common/ipc_channel.cc IPC::Channel::ProcessIncomingMessages(void)
+ chrome/common/ipc_channel.cc IPC::Channel::OnObjectSignaled(void *)
+ base/message_loop.cc MessageLoop::SignalWatcher(DWORD)
+ base/message_loop.cc MessageLoop::Run(Dispatcher::MessageLoop *)
+ base/message_loop.cc MessageLoop::Run(void)
+ chrome/common/ipc_tests.cc RunTestClient
+ chrome/common/ipc_tests.cc main
+ ...
+
+Uninitialized memory read in strlen
+Error Location
+ ...
+ chrome/common/ipc_tests.cc Send
+ chrome/common/ipc_tests.cc RunTestClient
+ chrome/common/ipc_tests.cc main
+ ...
+
+Uninitialized memory read in WriteFile
+Error Location
+ ...
+ chrome/common/ipc_channel.cc IPC::Channel::ProcessOutgoingMessages(void)
+ chrome/common/ipc_channel.cc IPC::Channel::Send(Message::IPC *)
+ chrome/common/ipc_tests.cc Send
+ chrome/common/ipc_tests.cc RunTestClient
+ chrome/common/ipc_tests.cc main
+ ...
+Alloc Location
+ ...
+ base/pickle.cc Pickle::Resize(UINT)
+ base/pickle.cc Pickle::BeginWrite(UINT)
+ base/pickle.cc Pickle::WriteBytes(void const*,int)
+ base/pickle.cc Pickle::WriteString(basic_string::std const&)
+ chrome/common/ipc_tests.cc Send
+ chrome/common/ipc_tests.cc RunTestClient
+ chrome/common/ipc_tests.cc main
+ ...
+
diff --git a/chrome/test/data/purify/unit_tests.exe.gtest.txt b/chrome/test/data/purify/unit_tests.exe.gtest.txt
new file mode 100644
index 0000000..4e83728
--- /dev/null
+++ b/chrome/test/data/purify/unit_tests.exe.gtest.txt
@@ -0,0 +1,2 @@
+# bug 1178136
+ImporterTest.Firefox3Importer
diff --git a/chrome/test/data/purify/unit_tests.exe_FIM.txt b/chrome/test/data/purify/unit_tests.exe_FIM.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/chrome/test/data/purify/unit_tests.exe_FIM.txt
diff --git a/chrome/test/data/purify/unit_tests.exe_FIM_flakey.txt b/chrome/test/data/purify/unit_tests.exe_FIM_flakey.txt
new file mode 100644
index 0000000..76276cb
--- /dev/null
+++ b/chrome/test/data/purify/unit_tests.exe_FIM_flakey.txt
@@ -0,0 +1,12 @@
+Freeing invalid memory in free
+Free Location
+ ...
+ chrome/third_party/hunspell/src/hunspell/hashmgr.cxx HashMgr::~HashMgr(void)
+ chrome/release/unit_tests.exe HashMgr::`scalar deleting destructor'(UINT)
+ chrome/third_party/hunspell/src/hunspell/hunspell.cxx Hunspell::~Hunspell(void)
+ chrome/release/unit_tests.exe Hunspell::`scalar deleting destructor'(UINT)
+ chrome/browser/spellchecker.cc SpellChecker::~SpellChecker(void)
+ chrome/renderer/spellcheck_unittest.cc SpellCheckTest_SpellCheckStrings_EN_US_Test::TestBody(void)
+ testing/gtest/src/gtest.cc testing::Test::Run(void)
+ ^^^
+
diff --git a/chrome/test/data/purify/unit_tests.exe_IPR.txt b/chrome/test/data/purify/unit_tests.exe_IPR.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/chrome/test/data/purify/unit_tests.exe_IPR.txt
diff --git a/chrome/test/data/purify/unit_tests.exe_MLK.txt b/chrome/test/data/purify/unit_tests.exe_MLK.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/chrome/test/data/purify/unit_tests.exe_MLK.txt
diff --git a/chrome/test/data/purify/unit_tests.exe_MLK_flakey.txt b/chrome/test/data/purify/unit_tests.exe_MLK_flakey.txt
new file mode 100644
index 0000000..951467c
--- /dev/null
+++ b/chrome/test/data/purify/unit_tests.exe_MLK_flakey.txt
@@ -0,0 +1,97 @@
+sqlite3GenericRealloc [unit_tests.exe]
+Alloc Location
+ ...
+ chrome/browser/history/history_unittest.cc history::HistoryProfileTest_TypicalProfileVersion_Test::TestBody(void)
+ testing/gtest/src/gtest.cc testing::Test::Run(void)
+ ^^^
+
+sqlite3GenericRealloc [unit_tests.exe]
+Alloc Location
+ ...
+ chrome/browser/history/history_unittest.cc history::HistoryProfileTest_TypicalProfileVersion_Test::TestBody(void)
+ testing/gtest/src/gtest.cc testing::Test::Run(void)
+ ^^^
+
+sqlite3GenericRealloc [unit_tests.exe]
+Alloc Location
+ ...
+ chrome/browser/history/history_unittest.cc history::HistoryProfileTest_TypicalProfileVersion_Test::TestBody(void)
+ testing/gtest/src/gtest.cc testing::Test::Run(void)
+ ^^^
+
+sqlite3GenericMalloc [unit_tests.exe]
+Alloc Location
+ ...
+ chrome/common/sqlite_utils.h SQLStatement::prepare(sqlite3 *,char const*,int)
+ chrome/common/sqlite_utils.h SQLStatement::prepare(sqlite3 *,char const*)
+ chrome/browser/history/history_unittest.cc history::HistoryProfileTest_TypicalProfileVersion_Test::TestBody(void)
+ testing/gtest/src/gtest.cc testing::Test::Run(void)
+ ^^^
+
+sqlite3GenericMalloc [unit_tests.exe]
+Alloc Location
+ ...
+ chrome/common/sqlite_utils.h SQLStatement::step(void)
+ chrome/browser/history/history_unittest.cc history::HistoryProfileTest_TypicalProfileVersion_Test::TestBody(void)
+ testing/gtest/src/gtest.cc testing::Test::Run(void)
+ ^^^
+
+TabStripModelTest::CreateTabContents(void) [unit_tests.exe]
+Alloc Location
+ ...
+ chrome/browser/tabs/tab_strip_model_unittest.cc TabStripModelTest::CreateTabContents(void)
+ chrome/browser/tabs/tab_strip_model_unittest.cc TabStripModelTest_TestBasicAPI_Test::TestBody(void)
+ testing/gtest/src/gtest.cc testing::Test::Run(void)
+ ^^^
+
+TabContents::SetupController(Profile *) [unit_tests.exe]
+Alloc Location
+ ...
+ chrome/browser/tab_contents.cc TabContents::SetupController(Profile *)
+ chrome/browser/tabs/tab_strip_model_unittest.cc TabStripModelTest::CreateTabContents(void)
+ chrome/browser/tabs/tab_strip_model_unittest.cc TabStripModelTest_TestBasicAPI_Test::TestBody(void)
+ testing/gtest/src/gtest.cc testing::Test::Run(void)
+ ^^^
+
+?_Allocate@U_Node@?$_List_nod@U?$pair@$$CBW4TabContentsType@@PAVTabContents@@@std@@V?$allocator@U?$pair@$$CBW4TabContentsType@@PAVTabContents@@@std@@@2@@std@@@std@@YAPAU_Node@?$_List_nod@U?$pair@$$CBW4TabContentsType@@PAVTabContents@@@std@@V?$allocator@U?$pair@$$CBW4TabContentsType@@PAVTabContents@@@std@@@2@@0@IPAU120@@Z [unit_tests.exe]
+Alloc Location
+ ...
+ chrome/browser/navigation_controller.cc NavigationController::NavigationController(TabContents *,Profile *)
+ chrome/browser/tab_contents.cc TabContents::SetupController(Profile *)
+ chrome/browser/tabs/tab_strip_model_unittest.cc TabStripModelTest::CreateTabContents(void)
+ chrome/browser/tabs/tab_strip_model_unittest.cc TabStripModelTest_TestBasicAPI_Test::TestBody(void)
+ testing/gtest/src/gtest.cc testing::Test::Run(void)
+ ^^^
+
+c:\b\slave\p\build\third_party\platformsdk_vista_6_0\files\vc\include\xmemory.
+Alloc Location
+ ...
+ chrome/browser/navigation_controller.cc NavigationController::NavigationController(TabContents *,Profile *)
+ chrome/browser/tab_contents.cc TabContents::SetupController(Profile *)
+ chrome/browser/tabs/tab_strip_model_unittest.cc TabStripModelTest::CreateTabContents(void)
+ chrome/browser/tabs/tab_strip_model_unittest.cc TabStripModelTest_TestBasicAPI_Test::TestBody(void)
+ testing/gtest/src/gtest.cc testing::Test::Run(void)
+ ^^^
+
+?_Allocate@U_Node@?$_List_nod@U?$pair@$$CBW4TabContentsType@@PAVTabContents@@@std@@V?$allocator@U?$pair@$$CBW4TabContentsType@@PAVTabContents@@@std@@@2@@std@@@std@@YAPAU_Node@?$_List_nod@U?$pair@$$CBW4TabContentsType@@PAVTabContents@@@std@@V?$allocator@U?$pair@$$CBW4TabContentsType@@PAVTabContents@@@std@@@2@@0@IPAU120@@Z [unit_tests.exe]
+Alloc Location
+ ...
+ chrome/browser/navigation_controller.cc NavigationController::RegisterTabContents(TabContents *)
+ chrome/browser/navigation_controller.cc NavigationController::NavigationController(TabContents *,Profile *)
+ chrome/browser/tab_contents.cc TabContents::SetupController(Profile *)
+ chrome/browser/tabs/tab_strip_model_unittest.cc TabStripModelTest::CreateTabContents(void)
+ chrome/browser/tabs/tab_strip_model_unittest.cc TabStripModelTest_TestBasicAPI_Test::TestBody(void)
+ testing/gtest/src/gtest.cc testing::Test::Run(void)
+ ^^^
+
+c:\b\slave\p\build\third_party\platformsdk_vista_6_0\files\vc\include\xmemory.
+Alloc Location
+ ...
+ chrome/browser/ssl_manager.cc SSLManager::SSLManager(NavigationController *,Delegate::SSLManager *)
+ chrome/browser/navigation_controller.cc NavigationController::NavigationController(TabContents *,Profile *)
+ chrome/browser/tab_contents.cc TabContents::SetupController(Profile *)
+ chrome/browser/tabs/tab_strip_model_unittest.cc TabStripModelTest::CreateTabContents(void)
+ chrome/browser/tabs/tab_strip_model_unittest.cc TabStripModelTest_TestBasicAPI_Test::TestBody(void)
+ testing/gtest/src/gtest.cc testing::Test::Run(void)
+ ^^^
+
diff --git a/chrome/test/data/purify/unit_tests.exe_UMR.txt b/chrome/test/data/purify/unit_tests.exe_UMR.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/chrome/test/data/purify/unit_tests.exe_UMR.txt
diff --git a/chrome/test/data/purify/unit_tests.exe_UMR_flakey.txt b/chrome/test/data/purify/unit_tests.exe_UMR_flakey.txt
new file mode 100644
index 0000000..a737c34
--- /dev/null
+++ b/chrome/test/data/purify/unit_tests.exe_UMR_flakey.txt
@@ -0,0 +1,100 @@
+Uninitialized memory read in WriteFile
+Error Location
+ ...
+ chrome/browser/session_backend.cc SessionBackend::AppendCommandsToFile(void *,vector::std const&)
+ chrome/browser/session_backend.cc SessionBackend::AppendCommands(vector::std *,bool)
+ chrome/browser/session_service.cc SessionService::Save(void)
+ chrome/browser/session_service.cc SessionService::~SessionService(void)
+ chrome/release/unit_tests.exe SessionService::`vector deleting destructor'(UINT)
+ base/ref_counted.h base::RefCountedThreadSafe::Release(void)
+ base/ref_counted.h scoped_refptr::=(SessionService *)
+ chrome/browser/session_service_test_helper.h SessionServiceTestHelper::set_service(SessionService *)
+ chrome/browser/session_service_unittest.cc SessionServiceTest::ReadWindows(vector::std *)
+ chrome/browser/session_service_unittest.cc SessionServiceTest_ClosingTabStaysClosed_Test::TestBody(void)
+ testing/gtest/src/gtest.cc testing::Test::Run(void)
+ ^^^
+Alloc Location
+ ...
+ chrome/browser/session_backend.cc SessionCommand::SessionCommand(BYTE,WORD)
+ chrome/browser/session_service.cc SessionService::CreateTabClosedCommand(int)
+ chrome/browser/session_service.cc SessionService::TabClosed(SessionID const&,SessionID const&)
+ chrome/browser/session_service_unittest.cc SessionServiceTest_ClosingTabStaysClosed_Test::TestBody(void)
+ testing/gtest/src/gtest.cc testing::Test::Run(void)
+ ^^^
+
+Uninitialized memory read in WriteFile
+Error Location
+ ...
+ chrome/browser/session_backend.cc SessionBackend::AppendCommandsToFile(void *,vector::std const&)
+ chrome/browser/session_backend.cc SessionBackend::AppendCommands(vector::std *,bool)
+ chrome/browser/session_service.cc SessionService::Save(void)
+ chrome/browser/session_service.cc SessionService::~SessionService(void)
+ chrome/release/unit_tests.exe SessionService::`vector deleting destructor'(UINT)
+ base/ref_counted.h base::RefCountedThreadSafe::Release(void)
+ base/ref_counted.h scoped_refptr::=(SessionService *)
+ chrome/browser/session_service_test_helper.h SessionServiceTestHelper::set_service(SessionService *)
+ chrome/browser/session_service_unittest.cc SessionServiceTest::ReadWindows(vector::std *)
+ chrome/browser/session_service_unittest.cc SessionServiceTest_WindowCloseCommittedAfterNavigate_Test::TestBody(void)
+ testing/gtest/src/gtest.cc testing::Test::Run(void)
+ ^^^
+Alloc Location
+ ...
+ chrome/browser/session_backend.cc SessionCommand::SessionCommand(BYTE,WORD)
+ chrome/browser/session_service.cc SessionService::CreateTabClosedCommand(int)
+ chrome/browser/session_service.cc SessionService::CommitPendingCloses(void)
+ chrome/browser/session_service.cc SessionService::UpdateTabNavigation(SessionID const&,int,NavigationEntry const&)
+ chrome/browser/session_service_unittest.cc SessionServiceTest::UpdateNavigation(SessionID const&,TabNavigation const&,bool)
+ chrome/browser/session_service_unittest.cc SessionServiceTest_WindowCloseCommittedAfterNavigate_Test::TestBody(void)
+ testing/gtest/src/gtest.cc testing::Test::Run(void)
+ ^^^
+
+Uninitialized memory read in WriteFile
+Error Location
+ ...
+ chrome/browser/session_backend.cc SessionBackend::AppendCommandsToFile(void *,vector::std const&)
+ chrome/browser/session_backend.cc SessionBackend::AppendCommands(vector::std *,bool)
+ chrome/browser/session_service.cc SessionService::Save(void)
+ chrome/browser/session_service.cc SessionService::~SessionService(void)
+ chrome/release/unit_tests.exe SessionService::`scalar deleting destructor'(UINT)
+ base/ref_counted.h base::RefCountedThreadSafe::Release(void)
+ base/ref_counted.h scoped_refptr::=(SessionService *)
+ chrome/browser/session_service_test_helper.h SessionServiceTestHelper::set_service(SessionService *)
+ chrome/browser/session_service_unittest.cc SessionServiceTest::ReadWindows(vector::std *)
+ chrome/browser/session_service_unittest.cc SessionServiceTest_WindowCloseCommittedAfterNavigate_Test::TestBody(void)
+ testing/gtest/src/gtest.cc testing::Test::Run(void)
+ ^^^
+Alloc Location
+ ...
+ chrome/browser/session_backend.cc SessionCommand::SessionCommand(BYTE,WORD)
+ chrome/browser/session_service.cc SessionService::CreateTabClosedCommand(int)
+ chrome/browser/session_service.cc SessionService::CommitPendingCloses(void)
+ chrome/browser/session_service.cc SessionService::UpdateTabNavigation(SessionID const&,int,NavigationEntry const&)
+ chrome/browser/session_service_unittest.cc SessionServiceTest::UpdateNavigation(SessionID const&,TabNavigation const&,bool)
+ chrome/browser/session_service_unittest.cc SessionServiceTest_WindowCloseCommittedAfterNavigate_Test::TestBody(void)
+ testing/gtest/src/gtest.cc testing::Test::Run(void)
+ ^^^
+
+Uninitialized memory read in WriteFile
+Error Location
+ ...
+ chrome/browser/session_backend.cc SessionBackend::AppendCommandsToFile(void *,vector::std const&)
+ chrome/browser/session_backend.cc SessionBackend::AppendCommands(vector::std *,bool)
+ chrome/browser/session_service.cc SessionService::Save(void)
+ chrome/browser/session_service.cc SessionService::~SessionService(void)
+ chrome/release/unit_tests.exe SessionService::`scalar deleting destructor'(UINT)
+ base/ref_counted.h base::RefCountedThreadSafe::Release(void)
+ base/ref_counted.h scoped_refptr::=(SessionService *)
+ chrome/browser/session_service_test_helper.h SessionServiceTestHelper::set_service(SessionService *)
+ chrome/browser/session_service_unittest.cc SessionServiceTest::ReadWindows(vector::std *)
+ chrome/browser/session_service_unittest.cc SessionServiceTest_ClosingTabStaysClosed_Test::TestBody(void)
+ testing/gtest/src/gtest.cc testing::Test::Run(void)
+ ^^^
+Alloc Location
+ ...
+ chrome/browser/session_backend.cc SessionCommand::SessionCommand(BYTE,WORD)
+ chrome/browser/session_service.cc SessionService::CreateTabClosedCommand(int)
+ chrome/browser/session_service.cc SessionService::TabClosed(SessionID const&,SessionID const&)
+ chrome/browser/session_service_unittest.cc SessionServiceTest_ClosingTabStaysClosed_Test::TestBody(void)
+ testing/gtest/src/gtest.cc testing::Test::Run(void)
+ ^^^
+
diff --git a/chrome/test/data/read_cookies.html b/chrome/test/data/read_cookies.html
new file mode 100644
index 0000000..b457c34
--- /dev/null
+++ b/chrome/test/data/read_cookies.html
@@ -0,0 +1,35 @@
+<html>
+<body>
+<pre>
+<script>
+
+// This script tests the performance of reading cookies. It sets a cookie and
+// then reads cookies N times. Finally, it outputs the average time taken to
+// read the cookie.
+
+document.cookie =
+ 'one_heck_of_a_crazy_cookie_name=1234567890.1234567890.1234567890.1234567890';
+
+var ok = true;
+
+var num_iters = document.location.search.substring(1) - 0;
+if (num_iters == 0)
+ num_iters = 10000;
+document.writeln("num_iters: " + num_iters);
+
+var ts = (new Date()).getTime();
+
+// read the cookie num_iters times
+for (var i = 0; i < num_iters; ++i) {
+ var d = document.cookie;
+}
+
+var te = (new Date()).getTime();
+
+var time_per_read = (te - ts) / num_iters;
+document.writeln("time per read: " + time_per_read.toFixed(3) + " msec");
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/chrome/test/data/ref_redirect.html b/chrome/test/data/ref_redirect.html
new file mode 100644
index 0000000..e42704a
--- /dev/null
+++ b/chrome/test/data/ref_redirect.html
@@ -0,0 +1,8 @@
+<!-- Test used by RedirectTest.ClientFragments to make sure non-user initiated
+location changes (within page) are flagged as client redirects.-->
+<html>
+ <body onload="document.location.href='#myanchor'">
+ <a name="myanchor">Anchor</a><br/>
+ </body>
+</html>
+
diff --git a/chrome/test/data/resource.h b/chrome/test/data/resource.h
new file mode 100644
index 0000000..7008da4
--- /dev/null
+++ b/chrome/test/data/resource.h
@@ -0,0 +1,23 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by resource.rc
+//
+#define IDS_SIMPLE 101
+#define IDS_PLACEHOLDERS 102
+#define IDS_PLACEHOLDERS_2 103
+#define IDS_PLACEHOLDERS_3 104
+
+#define IDS_LOCALE_BOOL 105
+#define IDS_LOCALE_INT 106
+#define IDS_LOCALE_STRING 107
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 108
+#define _APS_NEXT_COMMAND_VALUE 40001
+#define _APS_NEXT_CONTROL_VALUE 1001
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/chrome/test/data/resource.rc b/chrome/test/data/resource.rc
new file mode 100644
index 0000000..767b9db
--- /dev/null
+++ b/chrome/test/data/resource.rc
@@ -0,0 +1,80 @@
+// Microsoft Visual C++ generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "afxres.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 ""afxres.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE
+BEGIN
+ "\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// String Table
+//
+
+STRINGTABLE
+BEGIN
+ IDS_SIMPLE "Hello World!"
+ IDS_PLACEHOLDERS "Hello, $1. Your number is $2."
+ IDS_PLACEHOLDERS_2 "You owe me $$$1."
+ IDS_PLACEHOLDERS_3 "Hello, $2. Your number is $1."
+ IDS_LOCALE_BOOL "false"
+ IDS_LOCALE_INT "1"
+ IDS_LOCALE_STRING "hello"
+END
+
+#endif // English (U.S.) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/chrome/test/data/safe_browsing/download_update.py b/chrome/test/data/safe_browsing/download_update.py
new file mode 100644
index 0000000..6b100376
--- /dev/null
+++ b/chrome/test/data/safe_browsing/download_update.py
@@ -0,0 +1,33 @@
+import urllib,sys
+
+
+url = 'http://safebrowsing.clients.google.com/safebrowsing/downloads?client=googleclient&appver=1.0&pver=2.1'
+
+if len(sys.argv) == 1:
+ data = 'goog-phish-shavar;\ngoog-malware-shavar;\n'
+else:
+ post_data_file = sys.argv[1]
+ file = open(post_data_file, "r")
+ data = file.read()
+ file.close
+
+response = urllib.urlopen(url, data)
+
+response_file = open("response", "r+")
+response_file.write(response.read())
+response_file.seek(0)
+
+counter = 0
+
+for line in response_file:
+ if not line.startswith('u:'):
+ continue
+
+ chunk_url = 'http://' + line[2:]
+ filename = chunk_url[chunk_url.rfind('/') + 1:]
+ filename = "%03d" % counter + filename[0:filename.rfind('_')]
+ counter += 1
+
+ urllib.urlretrieve(chunk_url, filename)
+
+response_file.close() \ No newline at end of file
diff --git a/chrome/test/data/safe_browsing/initial/000goog-malware-shavar_s b/chrome/test/data/safe_browsing/initial/000goog-malware-shavar_s
new file mode 100644
index 0000000..2f70434
--- /dev/null
+++ b/chrome/test/data/safe_browsing/initial/000goog-malware-shavar_s
Binary files differ
diff --git a/chrome/test/data/safe_browsing/initial/001goog-malware-shavar_s b/chrome/test/data/safe_browsing/initial/001goog-malware-shavar_s
new file mode 100644
index 0000000..dd660ae
--- /dev/null
+++ b/chrome/test/data/safe_browsing/initial/001goog-malware-shavar_s
Binary files differ
diff --git a/chrome/test/data/safe_browsing/initial/002goog-malware-shavar_s b/chrome/test/data/safe_browsing/initial/002goog-malware-shavar_s
new file mode 100644
index 0000000..7d81aef
--- /dev/null
+++ b/chrome/test/data/safe_browsing/initial/002goog-malware-shavar_s
Binary files differ
diff --git a/chrome/test/data/safe_browsing/initial/003goog-malware-shavar_s b/chrome/test/data/safe_browsing/initial/003goog-malware-shavar_s
new file mode 100644
index 0000000..0f18dea
--- /dev/null
+++ b/chrome/test/data/safe_browsing/initial/003goog-malware-shavar_s
Binary files differ
diff --git a/chrome/test/data/safe_browsing/initial/004goog-malware-shavar_s b/chrome/test/data/safe_browsing/initial/004goog-malware-shavar_s
new file mode 100644
index 0000000..156d187
--- /dev/null
+++ b/chrome/test/data/safe_browsing/initial/004goog-malware-shavar_s
Binary files differ
diff --git a/chrome/test/data/safe_browsing/initial/005goog-malware-shavar_s b/chrome/test/data/safe_browsing/initial/005goog-malware-shavar_s
new file mode 100644
index 0000000..66f35f3
--- /dev/null
+++ b/chrome/test/data/safe_browsing/initial/005goog-malware-shavar_s
Binary files differ
diff --git a/chrome/test/data/safe_browsing/initial/006goog-malware-shavar_s b/chrome/test/data/safe_browsing/initial/006goog-malware-shavar_s
new file mode 100644
index 0000000..c13fbc3
--- /dev/null
+++ b/chrome/test/data/safe_browsing/initial/006goog-malware-shavar_s
Binary files differ
diff --git a/chrome/test/data/safe_browsing/initial/007goog-malware-shavar_s b/chrome/test/data/safe_browsing/initial/007goog-malware-shavar_s
new file mode 100644
index 0000000..8e30acb
--- /dev/null
+++ b/chrome/test/data/safe_browsing/initial/007goog-malware-shavar_s
Binary files differ
diff --git a/chrome/test/data/safe_browsing/initial/008goog-malware-shavar_s b/chrome/test/data/safe_browsing/initial/008goog-malware-shavar_s
new file mode 100644
index 0000000..58ccc45
--- /dev/null
+++ b/chrome/test/data/safe_browsing/initial/008goog-malware-shavar_s
Binary files differ
diff --git a/chrome/test/data/safe_browsing/initial/009goog-malware-shavar_s b/chrome/test/data/safe_browsing/initial/009goog-malware-shavar_s
new file mode 100644
index 0000000..ebca6c6
--- /dev/null
+++ b/chrome/test/data/safe_browsing/initial/009goog-malware-shavar_s
Binary files differ
diff --git a/chrome/test/data/safe_browsing/initial/010goog-malware-shavar_a b/chrome/test/data/safe_browsing/initial/010goog-malware-shavar_a
new file mode 100644
index 0000000..0bed13ca
--- /dev/null
+++ b/chrome/test/data/safe_browsing/initial/010goog-malware-shavar_a
Binary files differ
diff --git a/chrome/test/data/safe_browsing/initial/011goog-malware-shavar_a b/chrome/test/data/safe_browsing/initial/011goog-malware-shavar_a
new file mode 100644
index 0000000..dac6efd
--- /dev/null
+++ b/chrome/test/data/safe_browsing/initial/011goog-malware-shavar_a
Binary files differ
diff --git a/chrome/test/data/safe_browsing/initial/012goog-malware-shavar_a b/chrome/test/data/safe_browsing/initial/012goog-malware-shavar_a
new file mode 100644
index 0000000..06abcc5
--- /dev/null
+++ b/chrome/test/data/safe_browsing/initial/012goog-malware-shavar_a
Binary files differ
diff --git a/chrome/test/data/safe_browsing/initial/013goog-malware-shavar_a b/chrome/test/data/safe_browsing/initial/013goog-malware-shavar_a
new file mode 100644
index 0000000..0b1b2ce
--- /dev/null
+++ b/chrome/test/data/safe_browsing/initial/013goog-malware-shavar_a
Binary files differ
diff --git a/chrome/test/data/safe_browsing/initial/014goog-malware-shavar_a b/chrome/test/data/safe_browsing/initial/014goog-malware-shavar_a
new file mode 100644
index 0000000..27500b2
--- /dev/null
+++ b/chrome/test/data/safe_browsing/initial/014goog-malware-shavar_a
Binary files differ
diff --git a/chrome/test/data/safe_browsing/initial/015goog-phish-shavar_s b/chrome/test/data/safe_browsing/initial/015goog-phish-shavar_s
new file mode 100644
index 0000000..5571b11
--- /dev/null
+++ b/chrome/test/data/safe_browsing/initial/015goog-phish-shavar_s
Binary files differ
diff --git a/chrome/test/data/safe_browsing/initial/016goog-phish-shavar_s b/chrome/test/data/safe_browsing/initial/016goog-phish-shavar_s
new file mode 100644
index 0000000..588a9c3
--- /dev/null
+++ b/chrome/test/data/safe_browsing/initial/016goog-phish-shavar_s
Binary files differ
diff --git a/chrome/test/data/safe_browsing/initial/017goog-phish-shavar_s b/chrome/test/data/safe_browsing/initial/017goog-phish-shavar_s
new file mode 100644
index 0000000..a18cfc5
--- /dev/null
+++ b/chrome/test/data/safe_browsing/initial/017goog-phish-shavar_s
Binary files differ
diff --git a/chrome/test/data/safe_browsing/initial/018goog-phish-shavar_s b/chrome/test/data/safe_browsing/initial/018goog-phish-shavar_s
new file mode 100644
index 0000000..a6b7fad
--- /dev/null
+++ b/chrome/test/data/safe_browsing/initial/018goog-phish-shavar_s
Binary files differ
diff --git a/chrome/test/data/safe_browsing/initial/019goog-phish-shavar_s b/chrome/test/data/safe_browsing/initial/019goog-phish-shavar_s
new file mode 100644
index 0000000..672d40b
--- /dev/null
+++ b/chrome/test/data/safe_browsing/initial/019goog-phish-shavar_s
Binary files differ
diff --git a/chrome/test/data/safe_browsing/initial/020goog-phish-shavar_s b/chrome/test/data/safe_browsing/initial/020goog-phish-shavar_s
new file mode 100644
index 0000000..2b551cb
--- /dev/null
+++ b/chrome/test/data/safe_browsing/initial/020goog-phish-shavar_s
Binary files differ
diff --git a/chrome/test/data/safe_browsing/initial/021goog-phish-shavar_s b/chrome/test/data/safe_browsing/initial/021goog-phish-shavar_s
new file mode 100644
index 0000000..3bffe0f
--- /dev/null
+++ b/chrome/test/data/safe_browsing/initial/021goog-phish-shavar_s
Binary files differ
diff --git a/chrome/test/data/safe_browsing/initial/022goog-phish-shavar_s b/chrome/test/data/safe_browsing/initial/022goog-phish-shavar_s
new file mode 100644
index 0000000..d441b11
--- /dev/null
+++ b/chrome/test/data/safe_browsing/initial/022goog-phish-shavar_s
Binary files differ
diff --git a/chrome/test/data/safe_browsing/initial/023goog-phish-shavar_s b/chrome/test/data/safe_browsing/initial/023goog-phish-shavar_s
new file mode 100644
index 0000000..0593ff6
--- /dev/null
+++ b/chrome/test/data/safe_browsing/initial/023goog-phish-shavar_s
Binary files differ
diff --git a/chrome/test/data/safe_browsing/initial/024goog-phish-shavar_s b/chrome/test/data/safe_browsing/initial/024goog-phish-shavar_s
new file mode 100644
index 0000000..a08966a
--- /dev/null
+++ b/chrome/test/data/safe_browsing/initial/024goog-phish-shavar_s
Binary files differ
diff --git a/chrome/test/data/safe_browsing/initial/025goog-phish-shavar_s b/chrome/test/data/safe_browsing/initial/025goog-phish-shavar_s
new file mode 100644
index 0000000..cbc6de3
--- /dev/null
+++ b/chrome/test/data/safe_browsing/initial/025goog-phish-shavar_s
Binary files differ
diff --git a/chrome/test/data/safe_browsing/initial/026goog-phish-shavar_s b/chrome/test/data/safe_browsing/initial/026goog-phish-shavar_s
new file mode 100644
index 0000000..d77f24d
--- /dev/null
+++ b/chrome/test/data/safe_browsing/initial/026goog-phish-shavar_s
Binary files differ
diff --git a/chrome/test/data/safe_browsing/initial/027goog-phish-shavar_s b/chrome/test/data/safe_browsing/initial/027goog-phish-shavar_s
new file mode 100644
index 0000000..7469338
--- /dev/null
+++ b/chrome/test/data/safe_browsing/initial/027goog-phish-shavar_s
Binary files differ
diff --git a/chrome/test/data/safe_browsing/initial/028goog-phish-shavar_s b/chrome/test/data/safe_browsing/initial/028goog-phish-shavar_s
new file mode 100644
index 0000000..a317a27
--- /dev/null
+++ b/chrome/test/data/safe_browsing/initial/028goog-phish-shavar_s
Binary files differ
diff --git a/chrome/test/data/safe_browsing/initial/029goog-phish-shavar_s b/chrome/test/data/safe_browsing/initial/029goog-phish-shavar_s
new file mode 100644
index 0000000..cefbff0
--- /dev/null
+++ b/chrome/test/data/safe_browsing/initial/029goog-phish-shavar_s
Binary files differ
diff --git a/chrome/test/data/safe_browsing/initial/030goog-phish-shavar_s b/chrome/test/data/safe_browsing/initial/030goog-phish-shavar_s
new file mode 100644
index 0000000..458f1ab
--- /dev/null
+++ b/chrome/test/data/safe_browsing/initial/030goog-phish-shavar_s
Binary files differ
diff --git a/chrome/test/data/safe_browsing/initial/031goog-phish-shavar_s b/chrome/test/data/safe_browsing/initial/031goog-phish-shavar_s
new file mode 100644
index 0000000..415b39e
--- /dev/null
+++ b/chrome/test/data/safe_browsing/initial/031goog-phish-shavar_s
Binary files differ
diff --git a/chrome/test/data/safe_browsing/initial/032goog-phish-shavar_s b/chrome/test/data/safe_browsing/initial/032goog-phish-shavar_s
new file mode 100644
index 0000000..b31ed3746
--- /dev/null
+++ b/chrome/test/data/safe_browsing/initial/032goog-phish-shavar_s
Binary files differ
diff --git a/chrome/test/data/safe_browsing/initial/033goog-phish-shavar_s b/chrome/test/data/safe_browsing/initial/033goog-phish-shavar_s
new file mode 100644
index 0000000..9ca635a
--- /dev/null
+++ b/chrome/test/data/safe_browsing/initial/033goog-phish-shavar_s
Binary files differ
diff --git a/chrome/test/data/safe_browsing/initial/034goog-phish-shavar_s b/chrome/test/data/safe_browsing/initial/034goog-phish-shavar_s
new file mode 100644
index 0000000..57cccd6
--- /dev/null
+++ b/chrome/test/data/safe_browsing/initial/034goog-phish-shavar_s
Binary files differ
diff --git a/chrome/test/data/safe_browsing/initial/035goog-phish-shavar_s b/chrome/test/data/safe_browsing/initial/035goog-phish-shavar_s
new file mode 100644
index 0000000..0f4f981
--- /dev/null
+++ b/chrome/test/data/safe_browsing/initial/035goog-phish-shavar_s
Binary files differ
diff --git a/chrome/test/data/safe_browsing/initial/036goog-phish-shavar_s b/chrome/test/data/safe_browsing/initial/036goog-phish-shavar_s
new file mode 100644
index 0000000..f3a46d2
--- /dev/null
+++ b/chrome/test/data/safe_browsing/initial/036goog-phish-shavar_s
Binary files differ
diff --git a/chrome/test/data/safe_browsing/initial/037goog-phish-shavar_s b/chrome/test/data/safe_browsing/initial/037goog-phish-shavar_s
new file mode 100644
index 0000000..3c35575
--- /dev/null
+++ b/chrome/test/data/safe_browsing/initial/037goog-phish-shavar_s
Binary files differ
diff --git a/chrome/test/data/safe_browsing/initial/038goog-phish-shavar_s b/chrome/test/data/safe_browsing/initial/038goog-phish-shavar_s
new file mode 100644
index 0000000..9230663
--- /dev/null
+++ b/chrome/test/data/safe_browsing/initial/038goog-phish-shavar_s
Binary files differ
diff --git a/chrome/test/data/safe_browsing/initial/039goog-phish-shavar_s b/chrome/test/data/safe_browsing/initial/039goog-phish-shavar_s
new file mode 100644
index 0000000..32cdec4
--- /dev/null
+++ b/chrome/test/data/safe_browsing/initial/039goog-phish-shavar_s
Binary files differ
diff --git a/chrome/test/data/safe_browsing/initial/040goog-phish-shavar_s b/chrome/test/data/safe_browsing/initial/040goog-phish-shavar_s
new file mode 100644
index 0000000..bc32d54
--- /dev/null
+++ b/chrome/test/data/safe_browsing/initial/040goog-phish-shavar_s
Binary files differ
diff --git a/chrome/test/data/safe_browsing/initial/041goog-phish-shavar_s b/chrome/test/data/safe_browsing/initial/041goog-phish-shavar_s
new file mode 100644
index 0000000..2ff0a2a
--- /dev/null
+++ b/chrome/test/data/safe_browsing/initial/041goog-phish-shavar_s
Binary files differ
diff --git a/chrome/test/data/safe_browsing/initial/042goog-phish-shavar_s b/chrome/test/data/safe_browsing/initial/042goog-phish-shavar_s
new file mode 100644
index 0000000..586cbff
--- /dev/null
+++ b/chrome/test/data/safe_browsing/initial/042goog-phish-shavar_s
Binary files differ
diff --git a/chrome/test/data/safe_browsing/initial/043goog-phish-shavar_s b/chrome/test/data/safe_browsing/initial/043goog-phish-shavar_s
new file mode 100644
index 0000000..ad319749
--- /dev/null
+++ b/chrome/test/data/safe_browsing/initial/043goog-phish-shavar_s
Binary files differ
diff --git a/chrome/test/data/safe_browsing/initial/044goog-phish-shavar_s b/chrome/test/data/safe_browsing/initial/044goog-phish-shavar_s
new file mode 100644
index 0000000..6622fba
--- /dev/null
+++ b/chrome/test/data/safe_browsing/initial/044goog-phish-shavar_s
Binary files differ
diff --git a/chrome/test/data/safe_browsing/initial/045goog-phish-shavar_s b/chrome/test/data/safe_browsing/initial/045goog-phish-shavar_s
new file mode 100644
index 0000000..107d5d4
--- /dev/null
+++ b/chrome/test/data/safe_browsing/initial/045goog-phish-shavar_s
Binary files differ
diff --git a/chrome/test/data/safe_browsing/initial/046goog-phish-shavar_s b/chrome/test/data/safe_browsing/initial/046goog-phish-shavar_s
new file mode 100644
index 0000000..e8c6b9e
--- /dev/null
+++ b/chrome/test/data/safe_browsing/initial/046goog-phish-shavar_s
Binary files differ
diff --git a/chrome/test/data/safe_browsing/initial/047goog-phish-shavar_s b/chrome/test/data/safe_browsing/initial/047goog-phish-shavar_s
new file mode 100644
index 0000000..cd99328
--- /dev/null
+++ b/chrome/test/data/safe_browsing/initial/047goog-phish-shavar_s
Binary files differ
diff --git a/chrome/test/data/safe_browsing/initial/048goog-phish-shavar_a b/chrome/test/data/safe_browsing/initial/048goog-phish-shavar_a
new file mode 100644
index 0000000..9f0a267
--- /dev/null
+++ b/chrome/test/data/safe_browsing/initial/048goog-phish-shavar_a
Binary files differ
diff --git a/chrome/test/data/safe_browsing/initial/049goog-phish-shavar_a b/chrome/test/data/safe_browsing/initial/049goog-phish-shavar_a
new file mode 100644
index 0000000..fab1ea4
--- /dev/null
+++ b/chrome/test/data/safe_browsing/initial/049goog-phish-shavar_a
Binary files differ
diff --git a/chrome/test/data/safe_browsing/initial/050goog-phish-shavar_a b/chrome/test/data/safe_browsing/initial/050goog-phish-shavar_a
new file mode 100644
index 0000000..2ed4261
--- /dev/null
+++ b/chrome/test/data/safe_browsing/initial/050goog-phish-shavar_a
Binary files differ
diff --git a/chrome/test/data/safe_browsing/initial/051goog-phish-shavar_a b/chrome/test/data/safe_browsing/initial/051goog-phish-shavar_a
new file mode 100644
index 0000000..b5206f7
--- /dev/null
+++ b/chrome/test/data/safe_browsing/initial/051goog-phish-shavar_a
Binary files differ
diff --git a/chrome/test/data/safe_browsing/initial/052goog-phish-shavar_a b/chrome/test/data/safe_browsing/initial/052goog-phish-shavar_a
new file mode 100644
index 0000000..e3634f4
--- /dev/null
+++ b/chrome/test/data/safe_browsing/initial/052goog-phish-shavar_a
Binary files differ
diff --git a/chrome/test/data/safe_browsing/old/SafeBrowsing b/chrome/test/data/safe_browsing/old/SafeBrowsing
new file mode 100644
index 0000000..5a51ecd
--- /dev/null
+++ b/chrome/test/data/safe_browsing/old/SafeBrowsing
Binary files differ
diff --git a/chrome/test/data/safe_browsing/old/postdata b/chrome/test/data/safe_browsing/old/postdata
new file mode 100644
index 0000000..a049fbb
--- /dev/null
+++ b/chrome/test/data/safe_browsing/old/postdata
@@ -0,0 +1,2 @@
+goog-malware-shavar;a:8,10,29,38,40-43,63-86,88-115,118-126,128-134,136-142,144-148,150-159,161-168,170-177,179-180,184-186,188-190,192-196,198-211,213-244,246-251,253,262,269-299,301-308,310-313,329-331,333-346,348-366,368-413,415-416,418-419,421-532,534-535,537-539,541-583,585-589,591-617,619-623,625,627-632,634-637,639,645,647-648,650,652,663-664,666-669,673-674,680,684-685,687-688,691-692,695,697,699-701,705,708-711,713-714,716,718,720-727,730-731,734,741,748-751,754-755,760,764,766-767,771-772,776-780,782-784,786,789-790,793,796-799,801-804,806,808,812-814,816-817,820-821,824-826,829-831,833,836-839,841,843-845,847,849-850,852,854-857,861-864,869,871-873,875-878,884-885,888-889,891-893,895-898,900-903,909-914,919,921,923-932,934-941,944-946,949,953-954,958,962,964-967,970-971,974-977,979-981,985-987,989-991,993,1000-1001,1003,1005,1008-1009,1013,1019,1022-1023,1026-1027,1029-1031,1035-1038,1040,1049,1051,1053-1055,1063-1067,1069,1071-1072,1075-1077,1083,1087,1089,1093-1094,1096,1099-1101,1103,1106-1107,1110-1111,1115,1118-1119,1122,1126,1128-1129,1134,1139-1140,1146-1148,1150-1152,1154-1155,1157-1158,1162-1164,1170,1172,1175-1177,1179-1180,1182-1183,1185,1188,1192-1193,1197-1198,1200-1205,1207,1209,1212-1213,1216,1219,1222-1224,1226-1227,1229-1230,1233-1235,1238,1243-1244,1246,1250,1255-1256,1263,1265-1267,1270,1272-1273,1275-1276,1279,1281,1284-1285,1289-1290,1292-1293,1296,1299-1300,1303-1308,1310,1313-1314,1316-1324,1329,1333,1336,1343,1346,1348-1349,1351,1353,1355-1356,1359-1360,1362,1368,1374,1378-1387,1390-1391,1394-1395,1398-1399,1402-1403,1407,1411,1413,1416-1417,1419,1423,1425-1427,1431-1432,1434-1436,1438-1445,1448-1450,1452-1453,1455-1456,1458-1464,1466-1467,1469,1473,1477-1478,1482,1484,1486-1487,1490,1493,1497-1532,1535-1540,1542-1571,1573-1575,1577-1579,1581-1583,1585,1588-1592,1594,1597,1600,1607-1611,1618,1620-1627,1629-1631,1633,1693,1696,1726,1729,1731-1732,1738-1739,1742,1746-1749,1752-1755,1758,1773-1774,1792,1820,1823-1826,1851,1879,1884,1888,1894,1897,1901-1903,1906,1911-1912,1915,1919,1932,1936,1950,1953-1954,1956,1961-1962,1964-1965,1968-1972,1974,1976-1978,1981,1983,1989,1992,2000,2002-2007,2010-2011,2017,2025-2029,2031-2047,2065-2067,2071-2072,2074,2085,2091,2093-2096,2098-2102,2104,2107-2133,2135-2136,2138-2139,2141,2143-2169,2183-2192,2194-2198,2200-2208,2210-2218,2221,2224,2227,2260,2330-2331,2372,2378,2384-2387,2390,2392,2395,2397-2398,2400,2428-2431,2433-2441,2445-2446,2448-2449,2451-2455,2457,2462,2464,2466-2469,2471-2473,2475,2479-2486,2488-2496,2498-2502,2505,2508,2510,2512,2516,2518,2520-2535,2543-2546,2548-2551,2557,2561,2563-2565,2570-2578,2583,2585-2587,2589,2592-2593,2596-2607,2610,2615,2619-2622,2625-2627,2631-2632,2640-2649,2651,2653-2656,2664-2665,2668-2672,2674-2675,2679,2681,2683,2691-2692,2695-2700,2702-2721,2723-2726,2728-2736,2738,2742-2743,2745-2776,2778-2779,2781,2783,2785-2786,2790-2792,2794,2797-2978,2980-3186,3188-3190,3193-3197,3199-3205,3207-3208,3210-3211,3215-3216,3218-3219,3221,3223,3227-3229,3231-3232,3234-3237,3240,3242-3243,3245-3246,3249-3250,3252-3256,3258,3260,3263-3266,3268-3277,3279-3280,3284,3286,3289,3291-3295,3297,3299-3302,3305,3307-3311,3313-3326,3328-3331,3336-3338,3342,3345-3349,3351-3377,3379,3381-3383,3385-3391,3394-3399,3405-3420,3423-3424,3430,3432,3434,3436,3439-3742,3746-3747,3749,3751,3753-3786,3788-3789,3791-3792,3794-3803,3805-3809,3813-3918,3920,3922,3924,3926-3927,3929-3933,3935-3939,3941,3943-3945,3947-3957,3960-3961,3963-3966,3968-3970,3972-3973,3976,3978-3981,3983-4003,4005,4007-4008,4011-4023,4025,4027-4032,4034-4045,4047-4062,4065,4068-4070,4072-4073,4075-4080,4082-4083,4085-4095,4097-4100,4104-4114,4116-4122,4124-4127,4129-4141,4143-4149,4151-4159,4161-4170,4172-4197:s:1-3940
+goog-phish-shavar;a:27,60,79,90,93,105-106,3257,3331-3332,3338-3339,3347-3349,3351,3356-3358,3371,3442,3475,3478,3491,3498,3517,3576,3590-3591,3600-3602,3612,3715,3722-3723,3728,3733,3853,3997,4041-4043,4111,4152,4173-4174,4243,4258,4260,4275,4279,4305,4323,4330,4386,4403,4415,4520,4556,4562,4660-4661,4669,4679-4680,4684,4741,4814,4816,4822,4933,4938,4940,4961,4964,5068,5079,5081,5084,5110-5111,5116,5140,5193,5222,5236,5250,5313,5328,5351,5353,5358,5394-5395,5412,5444,5461-5463,5466-5467,5470,5475,5518-5519,5574,5587,5623,5714-5715,5730-5731,5734,5772,5810,5877,5939,5955,5957,6028,6039,6076,6084,6089,6120,6122,6147,6165,6177,6233,6280,6286,6364,6391,6407-6408,6429,6479,6508-6509,6537,6541,6551,6553,6572-6574,6576,6578-6580,6582-6583,6585-6587,6589-6598,6600,6603-6605,6607-6613,6615,6617-6618,6620-6625,6627-6632,6634-6635,6637-6638,6641-6642,6644-6649,6651-6652,6655-6657,6659,6661-6668,6670-6693,6695,6697-6699,6701-6706,6708-6728,6730-6732,6734,6736-6752,6754-6757,6759-6798,6800-6830,6832-6838,6840,6842-6844,6846-6852,6854,6856-6865,6867-6869,6872-6876,6878,6880-6886,6888-6910,6912,6914-6916,6918-6933,6935-6950,6953-6954,6957-6959,6963,6965-6977,6979-6980,6982-6992,6994-6999,7001-7008,7010-7012,7014-7023,7025-7027,7029-7037,7039-7063,7065-7078,7080-7084,7087-7088,7090-7106,7108-7116,7118-7121,7123,7126-7134,7136-7142,7144-7150,7152-7159,7161-7173,7175-7188,7191-7192,7194-7200,7202-7207,7209-7221,7223-7226,7228-7230,7232-7234,7236-7246,7248-7252,7255-7259,7261-7262,7264-7276,7278-7280,7282-7284,7286-7291,7293-7300,7302-7328,7330-7336,7338-7341,7343-7347,7349-7369,7371-7375,7377-7379,7381-7390,7396-7401,7403-7404,7406,7409-7410,7412-7414,7417-7427,7429-7430,7432-7435,7437-7443,7445-7447,7449-7451,7453-7456,7458,7460,7462-7477,7480-7489,7491,7493-7495,7497-7498,7500-7501,7503,7505,7507-7510,7512-7513,7515-7520,7522-7531,7533-7537,7540-7549,7551-7552,7554,7556,7558-7561,7563-7585,7587-7590,7593-7595,7597,7599-7608,7610-7612,7614-7616,7618-7624,7626,7628-7635,7637-7638,7640-7648,7650-7653,7655-7660,7662-7684,7686-7723,7726-7750,7752-7757,7759-7765,7768-7783,7786-7789,7791-7805,7807-7809,7811-7813,7815-7821,7823-7841,7843-7857,7859-7870,7872,7874-7876,7878-7879,7881,7883-7891,7893-7897,7899-7902,7904-7906,7908-7918,7920-7926,7928-7946,7948-8008,8010-8016,8018-8019,8021-8024,8026-8029,8031,8033-8045,8048-8049,8051-8087,8089-8134,8136-8146,8148-8152,8155-8195,8197-8215,8217-8219,8221-8222,8224-8259,8261-8263,8266-8282,8284-8287,8289-8292,8294,8296-8297,8300-8302,8304-8307,8309-8335,8337-8339,8341-8356,8358-8359,8361-8391,8393-8399,8402,8404-8409,8412-8419,8421-8425,8427,8431-8433,8435-8439,8441-8443,8446,8448-8464,8466,8468-8469,8471-8478,8480-8497,8499-8500,8502-8504,8506-8507,8510-8511,8513-8517,8519-8522,8524-8525,8527-8531,8533,8538-8539,8541-8546,8548-8552,8554-8570,8572,8574-8576,8578,8580-8597,8599-8619,8621-8638,8640-8661,8663-8684,8686-8689,8691-8706,8708-8731,8733-8736,8738-8762,8764-8777,8779-8782,8785-8788,8790-8797,8799-8801,8803-8813,8815-8833,8835-8837,8839-8848,8851-8856,8858-8867,8869-8890,8892-8893,8895-8899,8901-8915,8919-8925,8927,8932,8936-8940,8942-8943,8946,8948-8949,8951-8952,8955,8957,8959-8967,8970-8973,8975-8990,8992-8997,8999-9015,9017-9018,9020-9023,9025-9028,9030-9032,9034-9038,9040-9041,9044-9053,9055,9057-9058,9060-9127,9129-9138,9140-9142,9144-9150,9152,9154-9169,9171,9173-9178,9181-9183,9185-9197,9199-9202,9205-9209,9211-9212,9214-9215,9218-9219,9221-9232,9234-9238,9240-9278,9280-9287,9289,9291,9293-9303,9305-9306,9308-9310,9313-9315,9317-9321,9323-9326,9328-9331,9333,9335,9337,9339-9341,9343-9349,9352-9353,9355,9357-9362,9364-9367,9370-9382,9384-9401,9404-9406,9408-9411,9413-9424,9426-9444,9446-9448,9450-9465,9468-9471,9473-9475,9477,9479-9483,9486-9489,9491-9500,9502-9530,9532-9533,9535-9553,9555-9595,9597-9601,9603-9604,9606-9623,9625-9646,9648-9675,9677-9681,9683-9690,9692-9693,9695-9699,9701-9737,9739-9803,9805-9825,9827-9850,9852-9868,9870-9900,9902-9938,9940-9981,9983-10012,10014-10080,10082-10092,10094-10098,10100-10109,10111-10123,10125-10140,10142-10158,10160-10174,10176-10217,10219-10226,10228-10234,10236-10238,10241-10251,10253-10267,10271-10284,10286-10300,10302-10303,10305-10314,10316-10318,10320-10321,10323-10327,10329-10337,10339-10344,10346-10359,10361-10366,10368-10393,10395-10424,10426-10463,10465-10467,10470-10481,10484-10498,10501-10548,10550-10575,10578-10589,10591-10705,10707-10722,10724-10733,10735-10739,10741-10758,10760-10781,10783-10873,10875-10929,10931-10994,10996-11004,11006-11029,11031-11039,11041-11067:s:1-2045,2051-2060,2066-2100,2106-2110,2116-2145,2151-2160,2171-2180,2196-2260,2266-2280,2286-2325,2331-9209
diff --git a/chrome/test/data/safe_browsing/old/response b/chrome/test/data/safe_browsing/old/response
new file mode 100644
index 0000000..9e8dc94
--- /dev/null
+++ b/chrome/test/data/safe_browsing/old/response
@@ -0,0 +1,48 @@
+n:1835
+i:goog-malware-shavar
+ad:8,38,40-43,67,75,105,112-113,141,148,196,250-251,253,277,280,289,340,368,371,409,425,475,507,575,609,614,632,637,668,673,691,695,697,701,709-711,714,718,720-722,725-727,734,748,750,764,766,772,776,790,798-799,801,813,816,836,838-839,850,855,862,864,872,892,898,911,941,987,1001,1023,1026,1029,1031,1065,1069,1087,1094,1100,1107,1111,1115,1126,1129,1158,1172,1177,1182,1198,1202-1203,1219,1224,1230,1233-1234,1244,1265,1267,1275,1304,1314,1343,1346,1356,1359-1360,1368,1374,1391,1411,1413,1417,1427,1436,1444-1445,1452-1453,1455-1456,1459-1460,1462,1477,1484,1493,1510,1512,1539,1546,1554,1574,1594,1629,1726,1748,1753-1754,1774,1792,1824-1826,1884,1894,1897,1901-1903,1906,1974,1983,2026,2029,2036-2037,2041,2043,2045,2065,2116,2186,2192,2200,2204,2217-2218,2433,2437,2453,2455,2462,2464,2510,2535,2543,2546,2557,2585,2587,2592,2596-2597,2615,2645-2646,2691-2692,2698-2699,2711,2723,2753,2768-2769,2771,2783,2792,2794,2819,2842,2911,3032,3197,3208,3216,3221,3229,3234,3236-3237,3242,3255,3258,3265,3272-3274,3280,3286,3291-3294,3305,3328,3394,3423,3434,3746,3754,3785-3786,3797,3799,3806-3807,3896,3914,3917,3924,3927,3937,3941,3945,3952,3957,3969,3978-3979,3981,3984-3986,3991,3993,4015,4020-4022,4029-4030,4034,4038,4048,4051-4054,4069,4072,4076,4078,4080,4082,4085,4088-4089,4094,4104,4107,4114,4119-4121,4124,4126,4129,4131,4135,4139,4147,4152-4153,4158-4159,4163-4165,4167,4169,4178,4180,4182,4184,4187,4189-4191
+u:s.ytimg.com/safebrowsing/rd/goog-malware-shavar_s_3921-4000:3921-4000
+u:s.ytimg.com/safebrowsing/rd/goog-malware-shavar_s_4001-4080:4001-4080
+u:s.ytimg.com/safebrowsing/rd/goog-malware-shavar_s_4081-4160:4081-4160
+u:s.ytimg.com/safebrowsing/rd/goog-malware-shavar_s_4161-4240:4161-4240
+u:s.ytimg.com/safebrowsing/rd/goog-malware-shavar_s_4241-4280:4241-4280
+u:s.ytimg.com/safebrowsing/rd/goog-malware-shavar_s_4281-4320:4281-4320
+u:s.ytimg.com/safebrowsing/rd/goog-malware-shavar_s_4321-4400:4321-4400
+u:s.ytimg.com/safebrowsing/rd/goog-malware-shavar_s_4401-4480:4401-4418
+u:s.ytimg.com/safebrowsing/rd/goog-malware-shavar_a_4161-4320:4161-4162,4166,4168,4170,4172-4177,4179,4181,4183,4185-4186,4188,4192-4198,4208-4215,4219,4221-4224,4226-4231,4233-4235,4240-4242,4244-4246,4248-4251,4253-4262,4265-4269,4272,4274,4276-4279,4281-4283,4285-4289,4291-4300,4302-4303,4305-4311,4313-4314,4316,4318-4320
+u:s.ytimg.com/safebrowsing/rd/goog-malware-shavar_a_4321-4480:4321-4324,4326-4342,4344-4347,4349-4352,4354,4356,4358-4373,4375-4381,4383-4386,4389-4394,4396-4399,4401-4407,4409-4411,4413,4416-4423,4425-4426,4428,4430-4435,4438-4446,4448-4456,4458-4464,4466-4477,4479-4480
+u:s.ytimg.com/safebrowsing/rd/goog-malware-shavar_a_4481-4640:4481-4503,4505-4513,4515-4518,4520-4530
+i:goog-phish-shavar
+ad:27,60,90,93,105-106,3257,3331-3332,3338-3339,3347-3349,3351,3356-3358,3371,3442,3475,3478,3491,3498,3517,3576,3590-3591,3600-3602,3612,3715,3722-3723,3728,3733,3853,3997,4041-4043,4111,4152,4173-4174,4243,4258,4260,4275,4279,4305,4323,4330,4386,4403,4415,4520,4556,4562,4660-4661,4669,4679-4680,4684,4741,4814,4816,4822,4933,4938,4940,4961,4964,5068,5079,5081,5084,5110-5111,5116,5140,5193,5222,5236,5250,5328,5351,5353,5358,5394-5395,5412,5444,5461-5463,5466-5467,5470,5475,5518-5519,5574,5587,5623,5714,5730-5731,5734,5772,5955,6028,6076,6089,6165,6177,6280,6479,6551,6553,6572-6574,6576,6578-6580,6582-6583,6585-6587,6589-6598,6600,6603-6605,6607-6613,6615,6617-6618,6620-6625,6627-6632,6634-6635,6637-6638,6641-6642,6644-6649,6651-6652,6655-6657,6659,6661-6668,6670-6679,6681-6693,6695,6697-6699,6701-6706,6708-6727,6730-6732,6734,6736-6740,6742-6745,6747-6752,6755-6757,6759-6768,6770-6798,6800-6830,6832-6838,6840,6842-6844,6846-6852,6854,6856-6865,6867-6869,6872-6876,6878,6880-6886,6888-6901,6903,6905-6906,6908-6910,6912,6915,6919-6933,6935-6942,6944-6950,6953-6954,6957-6959,6963,6965-6977,6979-6980,6982-6992,6994-6999,7001,7004-7007,7012,7014-7023,7025-7027,7029-7032,7034-7037,7039-7040,7043,7045,7047,7049-7057,7061-7063,7065-7078,7080-7084,7087-7088,7090-7106,7108-7116,7118-7121,7123,7126-7130,7132,7136-7142,7146-7150,7152-7159,7161-7163,7165-7170,7172,7175-7179,7181-7188,7191-7192,7194-7200,7202-7207,7209-7219,7221,7223-7226,7228-7230,7232-7234,7236,7238-7246,7248-7252,7255-7257,7259,7261-7262,7265,7267-7276,7278-7280,7282-7284,7287,7289-7291,7293-7300,7302-7306,7308,7310-7328,7330-7336,7338-7341,7343,7345-7347,7349-7369,7371-7375,7377-7379,7381-7390,7396-7401,7403-7404,7406,7409-7410,7412-7414,7417-7427,7429-7430,7432-7435,7437-7443,7445-7447,7449-7451,7453-7456,7458,7460,7462-7477,7480-7489,7493-7495,7497-7498,7500-7501,7503,7505,7507-7509,7512-7513,7515-7517,7519-7520,7522-7526,7528-7531,7533-7537,7540-7549,7551-7552,7554,7556,7558-7561,7563-7585,7587-7590,7593-7595,7597,7599-7608,7610-7612,7614-7616,7618-7624,7626,7628-7629,7631-7632,7634,7638,7640-7648,7650-7651,7653,7655-7660,7662-7675,7678-7684,7686-7723,7726-7736,7739-7750,7752-7757,7759-7765,7768-7775,7777-7783,7786-7789,7791-7805,7807-7809,7811-7813,7815-7821,7823-7841,7843-7857,7859-7870,7872,7874-7876,7878-7879,7881,7883-7887,7889-7891,7893-7897,7899-7902,7904-7906,7908-7909,7911-7913,7915,7917-7918,7920-7925,7928-7946,7948-8008,8010-8016,8018-8019,8021-8024,8026-8029,8031,8033-8045,8048-8049,8052-8087,8089-8134,8136-8146,8148-8152,8155-8176,8178-8179,8181-8195,8197-8215,8217-8219,8221-8222,8224-8234,8236-8259,8261-8263,8266-8282,8284-8287,8289-8292,8294,8296-8297,8300-8302,8304-8307,8309-8335,8337-8339,8341,8343-8356,8358-8359,8361-8391,8393-8399,8402,8404-8409,8412-8419,8421-8425,8427,8431-8433,8435-8439,8441-8443,8446,8448-8464,8466,8468-8469,8471-8478,8480-8497,8499-8500,8502-8504,8506-8507,8510-8511,8513-8517,8519-8522,8524-8525,8527-8531,8533,8538-8539,8541-8543,8545-8546,8548-8552,8554-8562,8564-8570,8572,8574-8576,8578,8580-8597,8599-8619,8621-8636,8638,8640-8661,8663-8674,8676-8684,8686-8689,8691-8701,8703,8705-8706,8708-8712,8714-8729,8731,8733-8736,8738-8743,8746-8762,8764-8777,8779-8782,8785-8788,8790-8795,8797,8799-8801,8803-8813,8815-8821,8823-8824,8826-8833,8835-8837,8839-8848,8851-8856,8859,8861-8867,8869-8890,8892-8893,8895-8899,8901-8915,8919-8925,8927,8932,8936-8940,8942-8943,8946,8949,8952,8955,8957,8960-8961,8963-8967,8970-8973,8975-8990,8992-8995,8999-9012,9014-9015,9020-9021,9023,9025-9028,9030-9032,9034-9038,9040-9041,9045,9065,9073,9079,9100-9101,9107,9169,9187,9189,9193,9205,9215,9229-9230,9232,9234-9235,9241,9249,9253,9274,9276,9293,9333,9349,9373,9377,9382,9392,9394,9457,9528,9544,9558,9569,9572,9606,9677,9722,9748,9757,9808,9821,9866,9888,9891,9895,9916,9935,9957,9965,9969,9979,9986,10002,10005,10007,10023,10033,10051,10076,10078,10080,10098,10111,10193,10213-10214,10222,10224,10230,10237,10250,10272,10279,10434,10456,10481,10527,10584,10732,10813,10844-10845,10852,10911,10913,10956,10969,10982,10994,11008,11017,11032,11035,11055-11056,11058-11059,11064
+u:s.ytimg.com/safebrowsing/rd/goog-phish-shavar_s_9121-9280:9121-9280
+u:s.ytimg.com/safebrowsing/rd/goog-phish-shavar_s_9281-9440:9281-9440
+u:s.ytimg.com/safebrowsing/rd/goog-phish-shavar_s_9441-9600:9441-9600
+u:s.ytimg.com/safebrowsing/rd/goog-phish-shavar_s_9601-9760:9601-9760
+u:s.ytimg.com/safebrowsing/rd/goog-phish-shavar_s_9761-9920:9761-9920
+u:s.ytimg.com/safebrowsing/rd/goog-phish-shavar_s_9921-10080:9921-10080
+u:s.ytimg.com/safebrowsing/rd/goog-phish-shavar_s_10081-10240:10081-10240
+u:s.ytimg.com/safebrowsing/rd/goog-phish-shavar_s_10241-10400:10241-10303,10305-10306,10308-10309,10311-10313,10316-10323,10325-10335,10337-10344,10346,10349-10351,10353,10356-10361,10363-10370,10372-10373,10375-10378,10380-10394,10396-10399
+u:s.ytimg.com/safebrowsing/rd/goog-phish-shavar_s_10401-10405:10401-10405
+u:s.ytimg.com/safebrowsing/rd/goog-phish-shavar_s_10411-10415:10411-10415
+u:s.ytimg.com/safebrowsing/rd/goog-phish-shavar_s_10426-10430:10426-10430
+u:s.ytimg.com/safebrowsing/rd/goog-phish-shavar_s_10431-10435:10432-10435
+u:s.ytimg.com/safebrowsing/rd/goog-phish-shavar_s_10436-10440:10436,10438-10440
+u:s.ytimg.com/safebrowsing/rd/goog-phish-shavar_s_10441-10460:10441-10445,10447,10449-10456,10458-10459
+u:s.ytimg.com/safebrowsing/rd/goog-phish-shavar_s_10461-10465:10461-10463,10465
+u:s.ytimg.com/safebrowsing/rd/goog-phish-shavar_s_10481-10485:10481,10483-10485
+u:s.ytimg.com/safebrowsing/rd/goog-phish-shavar_s_10491-10495:10491,10493-10494
+u:s.ytimg.com/safebrowsing/rd/goog-phish-shavar_s_10501-10520:10501-10502,10506-10510,10513-10520
+u:s.ytimg.com/safebrowsing/rd/goog-phish-shavar_s_10521-10525:10521-10525
+u:s.ytimg.com/safebrowsing/rd/goog-phish-shavar_s_10531-10535:10531-10535
+u:s.ytimg.com/safebrowsing/rd/goog-phish-shavar_s_10536-10540:10536-10540
+u:s.ytimg.com/safebrowsing/rd/goog-phish-shavar_s_10546-10550:10546,10548-10550
+u:s.ytimg.com/safebrowsing/rd/goog-phish-shavar_s_10551-10555:10551-10555
+u:s.ytimg.com/safebrowsing/rd/goog-phish-shavar_s_10561-10720:10561-10568,10571-10578,10580-10600,10602-10610,10612-10614,10616-10618,10620-10630,10632-10636,10638-10644,10646-10647,10649-10660,10662-10665,10667-10673,10675,10677-10694,10696-10697,10699-10704,10708-10709,10711-10719
+u:s.ytimg.com/safebrowsing/rd/goog-phish-shavar_s_10721-10880:10721,10723-10726,10728-10730,10732,10734-10736,10738,10741-10753,10755-10756,10758,10760-10761,10763-10767,10770,10772-10774,10776-10777,10780-10781,10783-10790,10792-10816,10818-10824,10826-10828,10830-10848,10851-10853,10855-10856,10858-10862,10864,10866-10880
+u:s.ytimg.com/safebrowsing/rd/goog-phish-shavar_s_10881-11040:10881-10915,10917-10921,10923-10924,10926-10927,10929-10935,10937-10949,10951-10952,10954-11012,11014-11040
+u:s.ytimg.com/safebrowsing/rd/goog-phish-shavar_s_11041-11200:11041,11043-11046,11048-11086
+u:s.ytimg.com/safebrowsing/rd/goog-phish-shavar_a_12801-12960:12801-12814,12816-12827,12830-12833,12835-12870,12873-12878,12880-12883,12885-12888,12890-12932,12934-12937,12939-12944,12946-12953,12955-12957,12959-12960
+u:s.ytimg.com/safebrowsing/rd/goog-phish-shavar_a_12961-13120:12961,12963-12969,12971-12973,12975-13012,13014-13048,13050-13076,13078-13120
+u:s.ytimg.com/safebrowsing/rd/goog-phish-shavar_a_13121-13280:13121-13169,13171-13188,13190-13196,13198-13207,13209-13280
+u:s.ytimg.com/safebrowsing/rd/goog-phish-shavar_a_13281-13440:13281-13392,13394-13406,13408-13440
+u:s.ytimg.com/safebrowsing/rd/goog-phish-shavar_a_13441-13600:13441-13453,13455-13511,13513-13596
diff --git a/chrome/test/data/safe_browsing/old/updates/000goog-malware-shavar_s b/chrome/test/data/safe_browsing/old/updates/000goog-malware-shavar_s
new file mode 100644
index 0000000..c13fbc3
--- /dev/null
+++ b/chrome/test/data/safe_browsing/old/updates/000goog-malware-shavar_s
Binary files differ
diff --git a/chrome/test/data/safe_browsing/old/updates/001goog-malware-shavar_s b/chrome/test/data/safe_browsing/old/updates/001goog-malware-shavar_s
new file mode 100644
index 0000000..8e30acb
--- /dev/null
+++ b/chrome/test/data/safe_browsing/old/updates/001goog-malware-shavar_s
Binary files differ
diff --git a/chrome/test/data/safe_browsing/old/updates/002goog-malware-shavar_s b/chrome/test/data/safe_browsing/old/updates/002goog-malware-shavar_s
new file mode 100644
index 0000000..58ccc45
--- /dev/null
+++ b/chrome/test/data/safe_browsing/old/updates/002goog-malware-shavar_s
Binary files differ
diff --git a/chrome/test/data/safe_browsing/old/updates/003goog-malware-shavar_s b/chrome/test/data/safe_browsing/old/updates/003goog-malware-shavar_s
new file mode 100644
index 0000000..ebca6c6
--- /dev/null
+++ b/chrome/test/data/safe_browsing/old/updates/003goog-malware-shavar_s
Binary files differ
diff --git a/chrome/test/data/safe_browsing/old/updates/004goog-malware-shavar_s b/chrome/test/data/safe_browsing/old/updates/004goog-malware-shavar_s
new file mode 100644
index 0000000..83762db
--- /dev/null
+++ b/chrome/test/data/safe_browsing/old/updates/004goog-malware-shavar_s
Binary files differ
diff --git a/chrome/test/data/safe_browsing/old/updates/005goog-malware-shavar_s b/chrome/test/data/safe_browsing/old/updates/005goog-malware-shavar_s
new file mode 100644
index 0000000..e815f48
--- /dev/null
+++ b/chrome/test/data/safe_browsing/old/updates/005goog-malware-shavar_s
Binary files differ
diff --git a/chrome/test/data/safe_browsing/old/updates/006goog-malware-shavar_s b/chrome/test/data/safe_browsing/old/updates/006goog-malware-shavar_s
new file mode 100644
index 0000000..67aaa32
--- /dev/null
+++ b/chrome/test/data/safe_browsing/old/updates/006goog-malware-shavar_s
Binary files differ
diff --git a/chrome/test/data/safe_browsing/old/updates/007goog-malware-shavar_s b/chrome/test/data/safe_browsing/old/updates/007goog-malware-shavar_s
new file mode 100644
index 0000000..bfdf3ae0
--- /dev/null
+++ b/chrome/test/data/safe_browsing/old/updates/007goog-malware-shavar_s
Binary files differ
diff --git a/chrome/test/data/safe_browsing/old/updates/008goog-malware-shavar_a b/chrome/test/data/safe_browsing/old/updates/008goog-malware-shavar_a
new file mode 100644
index 0000000..567036e
--- /dev/null
+++ b/chrome/test/data/safe_browsing/old/updates/008goog-malware-shavar_a
Binary files differ
diff --git a/chrome/test/data/safe_browsing/old/updates/009goog-malware-shavar_a b/chrome/test/data/safe_browsing/old/updates/009goog-malware-shavar_a
new file mode 100644
index 0000000..530176e
--- /dev/null
+++ b/chrome/test/data/safe_browsing/old/updates/009goog-malware-shavar_a
Binary files differ
diff --git a/chrome/test/data/safe_browsing/old/updates/010goog-malware-shavar_a b/chrome/test/data/safe_browsing/old/updates/010goog-malware-shavar_a
new file mode 100644
index 0000000..86aeae0
--- /dev/null
+++ b/chrome/test/data/safe_browsing/old/updates/010goog-malware-shavar_a
Binary files differ
diff --git a/chrome/test/data/safe_browsing/old/updates/011goog-phish-shavar_s b/chrome/test/data/safe_browsing/old/updates/011goog-phish-shavar_s
new file mode 100644
index 0000000..b5f45ac
--- /dev/null
+++ b/chrome/test/data/safe_browsing/old/updates/011goog-phish-shavar_s
Binary files differ
diff --git a/chrome/test/data/safe_browsing/old/updates/012goog-phish-shavar_s b/chrome/test/data/safe_browsing/old/updates/012goog-phish-shavar_s
new file mode 100644
index 0000000..f290c4c
--- /dev/null
+++ b/chrome/test/data/safe_browsing/old/updates/012goog-phish-shavar_s
Binary files differ
diff --git a/chrome/test/data/safe_browsing/old/updates/013goog-phish-shavar_s b/chrome/test/data/safe_browsing/old/updates/013goog-phish-shavar_s
new file mode 100644
index 0000000..4fd80ca
--- /dev/null
+++ b/chrome/test/data/safe_browsing/old/updates/013goog-phish-shavar_s
Binary files differ
diff --git a/chrome/test/data/safe_browsing/old/updates/014goog-phish-shavar_s b/chrome/test/data/safe_browsing/old/updates/014goog-phish-shavar_s
new file mode 100644
index 0000000..1d4aaf5
--- /dev/null
+++ b/chrome/test/data/safe_browsing/old/updates/014goog-phish-shavar_s
Binary files differ
diff --git a/chrome/test/data/safe_browsing/old/updates/015goog-phish-shavar_s b/chrome/test/data/safe_browsing/old/updates/015goog-phish-shavar_s
new file mode 100644
index 0000000..1239e9d
--- /dev/null
+++ b/chrome/test/data/safe_browsing/old/updates/015goog-phish-shavar_s
Binary files differ
diff --git a/chrome/test/data/safe_browsing/old/updates/016goog-phish-shavar_s b/chrome/test/data/safe_browsing/old/updates/016goog-phish-shavar_s
new file mode 100644
index 0000000..c6ed638
--- /dev/null
+++ b/chrome/test/data/safe_browsing/old/updates/016goog-phish-shavar_s
Binary files differ
diff --git a/chrome/test/data/safe_browsing/old/updates/017goog-phish-shavar_s b/chrome/test/data/safe_browsing/old/updates/017goog-phish-shavar_s
new file mode 100644
index 0000000..7f6b873
--- /dev/null
+++ b/chrome/test/data/safe_browsing/old/updates/017goog-phish-shavar_s
Binary files differ
diff --git a/chrome/test/data/safe_browsing/old/updates/018goog-phish-shavar_s b/chrome/test/data/safe_browsing/old/updates/018goog-phish-shavar_s
new file mode 100644
index 0000000..376cc76
--- /dev/null
+++ b/chrome/test/data/safe_browsing/old/updates/018goog-phish-shavar_s
Binary files differ
diff --git a/chrome/test/data/safe_browsing/old/updates/019goog-phish-shavar_s b/chrome/test/data/safe_browsing/old/updates/019goog-phish-shavar_s
new file mode 100644
index 0000000..77a5f13
--- /dev/null
+++ b/chrome/test/data/safe_browsing/old/updates/019goog-phish-shavar_s
Binary files differ
diff --git a/chrome/test/data/safe_browsing/old/updates/020goog-phish-shavar_s b/chrome/test/data/safe_browsing/old/updates/020goog-phish-shavar_s
new file mode 100644
index 0000000..b30ea59
--- /dev/null
+++ b/chrome/test/data/safe_browsing/old/updates/020goog-phish-shavar_s
Binary files differ
diff --git a/chrome/test/data/safe_browsing/old/updates/021goog-phish-shavar_s b/chrome/test/data/safe_browsing/old/updates/021goog-phish-shavar_s
new file mode 100644
index 0000000..19fc988
--- /dev/null
+++ b/chrome/test/data/safe_browsing/old/updates/021goog-phish-shavar_s
Binary files differ
diff --git a/chrome/test/data/safe_browsing/old/updates/022goog-phish-shavar_s b/chrome/test/data/safe_browsing/old/updates/022goog-phish-shavar_s
new file mode 100644
index 0000000..e2b1119
--- /dev/null
+++ b/chrome/test/data/safe_browsing/old/updates/022goog-phish-shavar_s
Binary files differ
diff --git a/chrome/test/data/safe_browsing/old/updates/023goog-phish-shavar_s b/chrome/test/data/safe_browsing/old/updates/023goog-phish-shavar_s
new file mode 100644
index 0000000..e0981c9
--- /dev/null
+++ b/chrome/test/data/safe_browsing/old/updates/023goog-phish-shavar_s
Binary files differ
diff --git a/chrome/test/data/safe_browsing/old/updates/024goog-phish-shavar_s b/chrome/test/data/safe_browsing/old/updates/024goog-phish-shavar_s
new file mode 100644
index 0000000..40da8ddf
--- /dev/null
+++ b/chrome/test/data/safe_browsing/old/updates/024goog-phish-shavar_s
Binary files differ
diff --git a/chrome/test/data/safe_browsing/old/updates/025goog-phish-shavar_s b/chrome/test/data/safe_browsing/old/updates/025goog-phish-shavar_s
new file mode 100644
index 0000000..1192843
--- /dev/null
+++ b/chrome/test/data/safe_browsing/old/updates/025goog-phish-shavar_s
Binary files differ
diff --git a/chrome/test/data/safe_browsing/old/updates/026goog-phish-shavar_s b/chrome/test/data/safe_browsing/old/updates/026goog-phish-shavar_s
new file mode 100644
index 0000000..d46be87
--- /dev/null
+++ b/chrome/test/data/safe_browsing/old/updates/026goog-phish-shavar_s
Binary files differ
diff --git a/chrome/test/data/safe_browsing/old/updates/027goog-phish-shavar_s b/chrome/test/data/safe_browsing/old/updates/027goog-phish-shavar_s
new file mode 100644
index 0000000..c0bd6fe
--- /dev/null
+++ b/chrome/test/data/safe_browsing/old/updates/027goog-phish-shavar_s
Binary files differ
diff --git a/chrome/test/data/safe_browsing/old/updates/028goog-phish-shavar_s b/chrome/test/data/safe_browsing/old/updates/028goog-phish-shavar_s
new file mode 100644
index 0000000..db057c3
--- /dev/null
+++ b/chrome/test/data/safe_browsing/old/updates/028goog-phish-shavar_s
Binary files differ
diff --git a/chrome/test/data/safe_browsing/old/updates/029goog-phish-shavar_s b/chrome/test/data/safe_browsing/old/updates/029goog-phish-shavar_s
new file mode 100644
index 0000000..9aab307
--- /dev/null
+++ b/chrome/test/data/safe_browsing/old/updates/029goog-phish-shavar_s
Binary files differ
diff --git a/chrome/test/data/safe_browsing/old/updates/030goog-phish-shavar_s b/chrome/test/data/safe_browsing/old/updates/030goog-phish-shavar_s
new file mode 100644
index 0000000..81d3e0d
--- /dev/null
+++ b/chrome/test/data/safe_browsing/old/updates/030goog-phish-shavar_s
Binary files differ
diff --git a/chrome/test/data/safe_browsing/old/updates/031goog-phish-shavar_s b/chrome/test/data/safe_browsing/old/updates/031goog-phish-shavar_s
new file mode 100644
index 0000000..ed17d3d
--- /dev/null
+++ b/chrome/test/data/safe_browsing/old/updates/031goog-phish-shavar_s
Binary files differ
diff --git a/chrome/test/data/safe_browsing/old/updates/032goog-phish-shavar_s b/chrome/test/data/safe_browsing/old/updates/032goog-phish-shavar_s
new file mode 100644
index 0000000..f3bf19d
--- /dev/null
+++ b/chrome/test/data/safe_browsing/old/updates/032goog-phish-shavar_s
Binary files differ
diff --git a/chrome/test/data/safe_browsing/old/updates/033goog-phish-shavar_s b/chrome/test/data/safe_browsing/old/updates/033goog-phish-shavar_s
new file mode 100644
index 0000000..bdc5225
--- /dev/null
+++ b/chrome/test/data/safe_browsing/old/updates/033goog-phish-shavar_s
Binary files differ
diff --git a/chrome/test/data/safe_browsing/old/updates/034goog-phish-shavar_s b/chrome/test/data/safe_browsing/old/updates/034goog-phish-shavar_s
new file mode 100644
index 0000000..7484012
--- /dev/null
+++ b/chrome/test/data/safe_browsing/old/updates/034goog-phish-shavar_s
Binary files differ
diff --git a/chrome/test/data/safe_browsing/old/updates/035goog-phish-shavar_s b/chrome/test/data/safe_browsing/old/updates/035goog-phish-shavar_s
new file mode 100644
index 0000000..b47101a
--- /dev/null
+++ b/chrome/test/data/safe_browsing/old/updates/035goog-phish-shavar_s
Binary files differ
diff --git a/chrome/test/data/safe_browsing/old/updates/036goog-phish-shavar_s b/chrome/test/data/safe_browsing/old/updates/036goog-phish-shavar_s
new file mode 100644
index 0000000..b968557
--- /dev/null
+++ b/chrome/test/data/safe_browsing/old/updates/036goog-phish-shavar_s
Binary files differ
diff --git a/chrome/test/data/safe_browsing/old/updates/037goog-phish-shavar_s b/chrome/test/data/safe_browsing/old/updates/037goog-phish-shavar_s
new file mode 100644
index 0000000..9b4c333
--- /dev/null
+++ b/chrome/test/data/safe_browsing/old/updates/037goog-phish-shavar_s
Binary files differ
diff --git a/chrome/test/data/safe_browsing/old/updates/038goog-phish-shavar_a b/chrome/test/data/safe_browsing/old/updates/038goog-phish-shavar_a
new file mode 100644
index 0000000..1010871
--- /dev/null
+++ b/chrome/test/data/safe_browsing/old/updates/038goog-phish-shavar_a
Binary files differ
diff --git a/chrome/test/data/safe_browsing/old/updates/039goog-phish-shavar_a b/chrome/test/data/safe_browsing/old/updates/039goog-phish-shavar_a
new file mode 100644
index 0000000..666eeba
--- /dev/null
+++ b/chrome/test/data/safe_browsing/old/updates/039goog-phish-shavar_a
Binary files differ
diff --git a/chrome/test/data/safe_browsing/old/updates/040goog-phish-shavar_a b/chrome/test/data/safe_browsing/old/updates/040goog-phish-shavar_a
new file mode 100644
index 0000000..435c037
--- /dev/null
+++ b/chrome/test/data/safe_browsing/old/updates/040goog-phish-shavar_a
Binary files differ
diff --git a/chrome/test/data/safe_browsing/old/updates/041goog-phish-shavar_a b/chrome/test/data/safe_browsing/old/updates/041goog-phish-shavar_a
new file mode 100644
index 0000000..e13aab7
--- /dev/null
+++ b/chrome/test/data/safe_browsing/old/updates/041goog-phish-shavar_a
Binary files differ
diff --git a/chrome/test/data/safe_browsing/old/updates/042goog-phish-shavar_a b/chrome/test/data/safe_browsing/old/updates/042goog-phish-shavar_a
new file mode 100644
index 0000000..7179c57
--- /dev/null
+++ b/chrome/test/data/safe_browsing/old/updates/042goog-phish-shavar_a
Binary files differ
diff --git a/chrome/test/data/save_page/1.css b/chrome/test/data/save_page/1.css
new file mode 100644
index 0000000..750524d
--- /dev/null
+++ b/chrome/test/data/save_page/1.css
@@ -0,0 +1,3 @@
+body {
+ font-size: 20px;
+} \ No newline at end of file
diff --git a/chrome/test/data/save_page/1.png b/chrome/test/data/save_page/1.png
new file mode 100644
index 0000000..393f0ea
--- /dev/null
+++ b/chrome/test/data/save_page/1.png
Binary files differ
diff --git a/chrome/test/data/save_page/a.htm b/chrome/test/data/save_page/a.htm
new file mode 100644
index 0000000..986258b
--- /dev/null
+++ b/chrome/test/data/save_page/a.htm
@@ -0,0 +1,10 @@
+<html>
+ <head>
+ <title>
+ Test page for saving page feature
+ </title>
+ </head>
+ <body>
+ Can you see this sentence?
+ </body>
+</html> \ No newline at end of file
diff --git a/chrome/test/data/save_page/b.htm b/chrome/test/data/save_page/b.htm
new file mode 100644
index 0000000..485468b
--- /dev/null
+++ b/chrome/test/data/save_page/b.htm
@@ -0,0 +1,12 @@
+<html>
+ <head>
+ <title>
+ Test page for saving page feature
+ </title>
+ <link type="text/css" href="1.css" rel="stylesheet">
+ </head>
+ <body>
+ The picture below is the back button.<br>
+ <img src="1.png"> </img>
+ </body>
+</html> \ No newline at end of file
diff --git a/chrome/test/data/serializer_nested_test.js b/chrome/test/data/serializer_nested_test.js
new file mode 100644
index 0000000..cfea8e8
--- /dev/null
+++ b/chrome/test/data/serializer_nested_test.js
@@ -0,0 +1,17 @@
+{
+ "bool": true,
+ "dict": {
+ "bool": true,
+ "dict": {
+ "bees": "knees",
+ "cats": "meow"
+ },
+ "foos": "bar",
+ "list": [ 3.4, "second", null ]
+ },
+ "int": 42,
+ "list": [ 1, 2 ],
+ "null": null,
+ "real": 3.14,
+ "string": "hello"
+}
diff --git a/chrome/test/data/serializer_test.js b/chrome/test/data/serializer_test.js
new file mode 100644
index 0000000..446925e
--- /dev/null
+++ b/chrome/test/data/serializer_test.js
@@ -0,0 +1,8 @@
+{
+ "bool": true,
+ "int": 42,
+ "list": [ 1, 2 ],
+ "null": null,
+ "real": 3.14,
+ "string": "hello"
+}
diff --git a/chrome/test/data/serializer_test_nowhitespace.js b/chrome/test/data/serializer_test_nowhitespace.js
new file mode 100644
index 0000000..a1afdc5
--- /dev/null
+++ b/chrome/test/data/serializer_test_nowhitespace.js
@@ -0,0 +1 @@
+{"bool":true,"int":42,"list":[1,2],"null":null,"real":3.14,"string":"hello"} \ No newline at end of file
diff --git a/chrome/test/data/server-unavailable.html b/chrome/test/data/server-unavailable.html
new file mode 100644
index 0000000..364322d
--- /dev/null
+++ b/chrome/test/data/server-unavailable.html
@@ -0,0 +1 @@
+This file is boring; all the action's in the .mock-http-headers.
diff --git a/chrome/test/data/server-unavailable.html.mock-http-headers b/chrome/test/data/server-unavailable.html.mock-http-headers
new file mode 100644
index 0000000..5dd521b
--- /dev/null
+++ b/chrome/test/data/server-unavailable.html.mock-http-headers
@@ -0,0 +1,2 @@
+HTTP/1.0 503 Service Unavailable
+Content-type: text/html
diff --git a/chrome/test/data/session_history/bot1.html b/chrome/test/data/session_history/bot1.html
new file mode 100644
index 0000000..e213c72
--- /dev/null
+++ b/chrome/test/data/session_history/bot1.html
@@ -0,0 +1,6 @@
+<html>
+<head><title>bot1</title></head>
+<body>
+This is the bottom frame #1. Tests will load here.
+</body>
+</html>
diff --git a/chrome/test/data/session_history/bot2.html b/chrome/test/data/session_history/bot2.html
new file mode 100644
index 0000000..5d0228c
--- /dev/null
+++ b/chrome/test/data/session_history/bot2.html
@@ -0,0 +1,6 @@
+<html>
+<head><title>bot2</title></head>
+<body>
+This is the bottom frame #2.
+</body>
+</html>
diff --git a/chrome/test/data/session_history/bot3.html b/chrome/test/data/session_history/bot3.html
new file mode 100644
index 0000000..deb7837
--- /dev/null
+++ b/chrome/test/data/session_history/bot3.html
@@ -0,0 +1,7 @@
+<html>
+<head><title>bot3</title></head>
+<body>
+Bottom frame the third.
+</body>
+</html>
+
diff --git a/chrome/test/data/session_history/form.html b/chrome/test/data/session_history/form.html
new file mode 100644
index 0000000..f20e02d
--- /dev/null
+++ b/chrome/test/data/session_history/form.html
@@ -0,0 +1,31 @@
+<html>
+<head>
+<title>form</title>
+<script>
+// Simulate the user clicking on the submit button.
+function submitForm(name) {
+ var node = document.getElementById(name);
+ node.click();
+}
+// Simulate the user filling a form value.
+function fillForm(name, value) {
+ var node = document.getElementById(name);
+ node.value = value;
+}
+</script>
+</head>
+<body>
+
+<form method="post" action="/echotitle">
+
+<p><input name="text" id="itext">
+<p><select name="select" id="iselect">
+ <option selected>a
+ <option>b
+ <option>c
+</select>
+<p><input type="submit" value="Submit" id="isubmit">
+
+</form>
+</body>
+</html>
diff --git a/chrome/test/data/session_history/fragment.html b/chrome/test/data/session_history/fragment.html
new file mode 100644
index 0000000..b5d6601
--- /dev/null
+++ b/chrome/test/data/session_history/fragment.html
@@ -0,0 +1,12 @@
+<html>
+<head><title>fragment</title></head>
+<body>
+A page with anchor fragment targets.
+<p>
+<a name="a">What's this? A reference fragment?</a>
+<p>
+<a name="b">And another!</a>
+<p>
+<a name="c">Last one, I promise.</a>
+</body>
+</html>
diff --git a/chrome/test/data/session_history/frames.html b/chrome/test/data/session_history/frames.html
new file mode 100644
index 0000000..a28c4e6
--- /dev/null
+++ b/chrome/test/data/session_history/frames.html
@@ -0,0 +1,45 @@
+<html>
+<head>
+<title>bot1</title>
+<script>
+// --- Convenience functions for testing.
+function setTitle() {
+ var fbot = document.getElementById("fbot");
+ document.title = fbot.contentDocument.title;
+}
+// Simulate the user clicking a link.
+function clickLink(name) {
+ var ftop = document.getElementById("ftop");
+ var node = ftop.contentDocument.getElementById(name);
+ var evt = document.createEvent("MouseEvents");
+ evt.initMouseEvent("click", true, true, window, 0, 0, 0, 0, 0,
+ false, false, false, false, 0, null);
+ node.dispatchEvent(evt);
+}
+// Simulate the user filling a form value.
+function fillForm(name, value) {
+ var fbot = document.getElementById("fbot");
+ var node = fbot.contentDocument.getElementById(name);
+ node.value = value;
+}
+// Simulate the user clicking on the submit button.
+function submitForm(name) {
+ var fbot = document.getElementById("fbot");
+ var node = fbot.contentDocument.getElementById(name);
+ node.click();
+}
+function init() {
+ var fbot = document.getElementById("fbot");
+ // This will set our title to the bottom frame, so we can test that
+ // we actually navigated.
+ fbot.onload = setTitle;
+}
+</script>
+</head>
+
+<frameset onLoad="init()" rows="20%,80%" name="main">
+ <frame src="top.html" id="ftop" name="top">
+ <frame src="bot1.html" id="fbot" name="bottom">
+</frameset>
+
+</html>
diff --git a/chrome/test/data/session_history/no-title.html b/chrome/test/data/session_history/no-title.html
new file mode 100644
index 0000000..ff70517
--- /dev/null
+++ b/chrome/test/data/session_history/no-title.html
@@ -0,0 +1 @@
+<body>no title specified</body>
diff --git a/chrome/test/data/session_history/post.html b/chrome/test/data/session_history/post.html
new file mode 100644
index 0000000..ab89b76
--- /dev/null
+++ b/chrome/test/data/session_history/post.html
@@ -0,0 +1,28 @@
+<html>
+<head>
+<title>post</title>
+<script>
+// stolen from darin's page cycler
+var options = location.search.substring(1).split('&');
+
+function getopt(name) {
+ var r = new RegExp("^" + name + "=");
+ for (i = 0; i < options.length; ++i) {
+ if (options[i].match(r)) {
+ return options[i].substring(name.length + 1);
+ }
+ }
+ return null;
+}
+
+function checkParams() {
+ document.title = "post:" + getopt("text") + "," + getopt("select");
+}
+checkParams();
+</script>
+</head>
+
+<body>
+Form submission accepted. Thanks for playing.
+</body>
+</html>
diff --git a/chrome/test/data/session_history/replace.html b/chrome/test/data/session_history/replace.html
new file mode 100644
index 0000000..4c79a6f
--- /dev/null
+++ b/chrome/test/data/session_history/replace.html
@@ -0,0 +1,4 @@
+<html>
+<head><title>redirecting</title></head>
+<body onload="location.replace(location.search.substring(1))">redirecting...</body>
+</html>
diff --git a/chrome/test/data/session_history/top.html b/chrome/test/data/session_history/top.html
new file mode 100644
index 0000000..70e3c71
--- /dev/null
+++ b/chrome/test/data/session_history/top.html
@@ -0,0 +1,8 @@
+<html>
+<body>
+<a href="bot1.html" id="abot1" target="bottom">bot1</a>
+<a href="bot2.html" id="abot2" target="bottom">bot2</a>
+<a href="bot3.html" id="abot3" target="bottom">bot3</a>
+<a href="form.html" id="aform" target="bottom">form</a>
+</body>
+</html>
diff --git a/chrome/test/data/ssl/bad_iframe.html b/chrome/test/data/ssl/bad_iframe.html
new file mode 100644
index 0000000..53eff7e
--- /dev/null
+++ b/chrome/test/data/ssl/bad_iframe.html
@@ -0,0 +1,10 @@
+<html>
+<script>
+ window.open('google.html', name,
+ "status = 1, height = 300, width = 300, resizable = 0" );
+</script>
+
+<H1>Evil IFrame</H1>
+This frame is loaded over insecure HTTPS.
+
+</html>
diff --git a/chrome/test/data/ssl/google.html b/chrome/test/data/ssl/google.html
new file mode 100644
index 0000000..3ef1ca1
--- /dev/null
+++ b/chrome/test/data/ssl/google.html
@@ -0,0 +1,4 @@
+<html><head><meta http-equiv="content-type" content="text/html; charset=UTF-8"><title>Google</title><style>body,td,a,p,.h{font-family:arial,sans-serif}.h{font-size:20px}.h{color:#3366cc}.q{color:#00c}.ts td{padding:0}.ts{border-collapse:collapse}#gbar{float:left;font-weight:bold;height:22px;padding-left:2px}.gbh,.gb2 div{border-top:1px solid #c9d7f1;font-size:0;height:0}.gbh{position:absolute;top:24px;width:100%}.gb2 div{margin:5px}#gbi{background:#fff;border:1px solid;border-color:#c9d7f1 #36c #36c #a2bae7;font-size:13px;top:24px;z-index:1000}#guser{padding-bottom:7px !important}#gbar,#guser{font-size:13px;padding-top:1px !important}@media all{.gb1,.gb3{height:22px;margin-right:.73em;vertical-align:top}.gb2 a{display:block;padding:.2em .5em}}#gbi,.gb2{display:none;position:absolute;width:8em}.gb2{z-index:1001}#gbar a,#gbar a:active,#gbar a:visited{color:#00c;font-weight:normal}.gb2 a,.gb3 a{text-decoration:none}#gbar .gb2 a:hover{background:#36c;color:#fff;display:block}</style><script>window.google={kEI:"BuG9R7b_PI6SoASYhdTtDQ",kEXPI:"17259,17735,17870",kHL:"en"};
+function sf(){document.f.q.focus()}
+window.rwt=function(b,d,e,g,h,f,i){var a=encodeURIComponent||escape,c=b.href.split("#");b.href="/url?sa=t"+(d?"&oi="+a(d):"")+(e?"&cad="+a(e):"")+"&ct="+a(g)+"&cd="+a(h)+"&url="+a(c[0]).replace(/\+/g,"%2B")+"&ei=BuG9R7b_PI6SoASYhdTtDQ"+(f?"&usg="+f:"")+i+(c[1]?"#"+c[1]:"");b.onmousedown="";return true};
+window.gbar={};(function(){var a=window.gbar,b,g,h;function l(c,f,e){c.display=h?"none":"block";c.left=f+"px";c.top=e+"px"}a.tg=function(c){var f=0,e=0,d,m=0,n,j=window.navExtra,k,i=document;g=g||i.getElementById("gbar").getElementsByTagName("span");(c||window.event).cancelBubble=!m;if(!b){b=i.createElement(Array.every||window.createPopup?"iframe":"DIV");b.frameBorder="0";b.scrolling="no";b.src="#";g[7].parentNode.appendChild(b).id="gbi";if(j&&g[7])for(n in j){k=i.createElement("span");k.appendChild(j[n]);g[7].parentNode.insertBefore(k,g[7]).className="gb2"}i.onclick=a.close}while(d=g[++m]){if(e){l(d.style,e+1,f+25);f+=d.firstChild.tagName=="DIV"?9:20}if(d.className=="gb3"){do e+=d.offsetLeft;while(d=d.offsetParent)}}b.style.height=f+"px";l(b.style,e,24);h=!h};a.close=function(c){h&&a.tg(c)}})();</script></head><body onload="sf();if(document.images){new Image().src='/images/nav_logo3.png'}" topmargin="3" alink="#ff0000" bgcolor="#ffffff" link="#0000cc" marginheight="3" text="#000000" vlink="#551a8b"><div id="gbar"><nobr><span class="gb1">Web</span> <span class="gb1"><a href="http://images.google.com/imghp?hl=en&amp;tab=wi">Images</a></span> <span class="gb1"><a href="http://maps.google.com/maps?hl=en&amp;tab=wl">Maps</a></span> <span class="gb1"><a href="http://news.google.com/nwshp?hl=en&amp;tab=wn">News</a></span> <span class="gb1"><a href="http://www.google.com/prdhp?hl=en&amp;tab=wf">Shopping</a></span> <span class="gb1"><a href="http://mail.google.com/mail/?hl=en&amp;tab=wm">Gmail</a></span> <span class="gb3"><a href="http://www.google.com/intl/en/options/" onclick="this.blur();gbar.tg(event);return !1"><u>more</u> <small>▼</small></a></span> <span class="gb2"><a href="http://video.google.com/?hl=en&amp;tab=wv">Video</a></span> <span class="gb2"><a href="http://groups.google.com/grphp?hl=en&amp;tab=wg">Groups</a></span> <span class="gb2"><a href="http://books.google.com/bkshp?hl=en&amp;tab=wp">Books</a></span> <span class="gb2"><a href="http://scholar.google.com/schhp?hl=en&amp;tab=ws">Scholar</a></span> <span class="gb2"><a href="http://finance.google.com/finance?hl=en&amp;tab=we">Finance</a></span> <span class="gb2"><a href="http://blogsearch.google.com/?hl=en&amp;tab=wb">Blogs</a></span> <span class="gb2"><div></div></span> <span class="gb2"><a href="http://www.youtube.com/?hl=en&amp;tab=w1">YouTube</a></span> <span class="gb2"><a href="http://www.google.com/calendar/render?hl=en&amp;tab=wc">Calendar</a></span> <span class="gb2"><a href="http://picasaweb.google.com/home?hl=en&amp;tab=wq">Photos</a></span> <span class="gb2"><a href="http://docs.google.com/?hl=en&amp;tab=wo">Documents</a></span> <span class="gb2"><a href="http://www.google.com/reader/view/?hl=en&amp;tab=wy">Reader</a></span> <span class="gb2"><div></div></span> <span class="gb2"><a href="http://www.google.com/intl/en/options/">even more »</a></span> </nobr></div><div class="gbh" style="left: 0pt;"></div><div class="gbh" style="right: 0pt;"></div><div id="guser" style="padding: 0pt 0pt 4px; font-size: 84%;" width="100%" align="right"><nobr><b>jcampan@gmail.com</b> | <a href="http://www.google.com/url?sa=p&amp;pref=ig&amp;pval=3&amp;q=http://www.google.com/ig%3Fhl%3Den%26source%3Diglk&amp;usg=AFQjCNFA18XPfgb7dKnXfKz7x7g1GDH1tg">iGoogle</a> | <a href="https://www.google.com/accounts/ManageAccount">My Account</a> | <a href="http://www.google.com/accounts/Logout?continue=http://www.google.com/">Sign out</a></nobr></div><center><br id="lgpd" clear="all"><img alt="Google" src="google_files/logo.gif" height="110" width="276"><br><br><form action="/search" name="f"><table cellpadding="0" cellspacing="0"><tbody><tr valign="top"><td width="25%">&nbsp;</td><td align="center" nowrap="nowrap"><input name="hl" value="en" type="hidden"><input maxlength="2048" name="q" size="55" title="Google Search" value=""><br><input name="btnG" value="Google Search" type="submit"><input name="btnI" value="I'm Feeling Lucky" type="submit"></td><td nowrap="nowrap" width="25%"><font size="-2">&nbsp;&nbsp;<a href="http://www.google.com/advanced_search?hl=en">Advanced Search</a><br>&nbsp;&nbsp;<a href="http://www.google.com/preferences?hl=en">Preferences</a><br>&nbsp;&nbsp;<a href="http://www.google.com/language_tools?hl=en">Language Tools</a></font></td></tr></tbody></table></form><br><br><font size="-1"><a href="http://www.google.com/intl/en/ads/">Advertising&nbsp;Programs</a> - <a href="http://www.google.com/services/">Business Solutions</a> - <a href="http://www.google.com/intl/en/about.html">About Google</a></font><p><font size="-2">©2008 Google</font></p></center></body></html> \ No newline at end of file
diff --git a/chrome/test/data/ssl/google_files/logo.gif b/chrome/test/data/ssl/google_files/logo.gif
new file mode 100644
index 0000000..afa22bc
--- /dev/null
+++ b/chrome/test/data/ssl/google_files/logo.gif
Binary files differ
diff --git a/chrome/test/data/ssl/page_with_dynamic_mixed_contents.html b/chrome/test/data/ssl/page_with_dynamic_mixed_contents.html
new file mode 100644
index 0000000..9ff73bb
--- /dev/null
+++ b/chrome/test/data/ssl/page_with_dynamic_mixed_contents.html
@@ -0,0 +1,36 @@
+<html>
+<head><title>Page with dynamic mixed contents</title>
+
+<script>
+ function loadBadImage() {
+ var image = document.getElementById("my_image");
+ image.src = "http://localhost:1337/files/ssl/google_files/logo.gif";
+ checkForLoadFinished();
+ }
+
+ function checkForLoadFinished() {
+ var image = document.getElementById("my_image");
+ if (image.complete) {
+ document.getElementById("status_text").innerHTML = "Bad image loaded";
+ window.domAutomationController.send(true);
+ } else {
+ setTimeout("checkForLoadFinished()", 500);
+ }
+ }
+</script>
+
+</head>
+<body>
+
+This page has some java-script that loads some mixed contents.
+<br><br>
+You can also press the button below to load the image.
+<br>
+<input type=button value="Load image" onclick="loadBadImage();"></input>
+
+<div id="status_text">Contents is OK</div>
+<img id="my_image" src=""/>
+
+
+</body>
+</html>
diff --git a/chrome/test/data/ssl/page_with_mixed_contents.html b/chrome/test/data/ssl/page_with_mixed_contents.html
new file mode 100644
index 0000000..2bf9bb24
--- /dev/null
+++ b/chrome/test/data/ssl/page_with_mixed_contents.html
@@ -0,0 +1,9 @@
+<html>
+<head><title>Page with mixed contents</title></head>
+<body>
+This page contains an image which is served over an http connection,
+causing mixed contents (when this page is loaded over https).<br>
+<img src="http://localhost:1337/files/ssl/google_files/logo.gif"/>
+
+</body>
+</html>
diff --git a/chrome/test/data/ssl/page_with_refs.html b/chrome/test/data/ssl/page_with_refs.html
new file mode 100644
index 0000000..3db0e5d
--- /dev/null
+++ b/chrome/test/data/ssl/page_with_refs.html
@@ -0,0 +1,21 @@
+<html>
+<head>
+<title>This page has refs</title>
+</head>
+<a href="#en">English<a><br>
+<a href="#fr">Francais<a><br>
+<a href="#jp">Japanese<a><br>
+<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
+<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
+<h2 id="en">Hello!</h2>
+<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
+<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
+<h2 id="fr">Bonjour!</h2><br><br>
+<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
+<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
+<h2 id="jp">Konnichiwa</h2><br><br>
+<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
+<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
+</html>
+
+
diff --git a/chrome/test/data/ssl/page_with_unsafe_contents.html b/chrome/test/data/ssl/page_with_unsafe_contents.html
new file mode 100644
index 0000000..907c9ca
--- /dev/null
+++ b/chrome/test/data/ssl/page_with_unsafe_contents.html
@@ -0,0 +1,30 @@
+<html>
+<head><title>Page with unsafe contents</title>
+<script>
+ var foo = null;
+
+ function IsFooSet() {
+ return foo != null;
+ }
+
+ function ImageWidth() {
+ return document.getElementById("bad_image").width;
+ }
+</script>
+<script src="https://127.0.0.1:9666/files/ssl/set_foo.js"></script>
+</head>
+
+<body>
+This page contains an image which is served over an insecure HTTPS connection...<br>
+<img id="bad_image" src="https://127.0.0.1:9666/files/ssl/google_files/logo.gif"/>
+
+<br><br>
+And an IFrame served over insecure HTTPS...<br>
+<iframe id="bad_iframe" src="https://127.0.0.1:9666/files/ssl/bad_iframe.html"/>
+
+<br><br>
+And even worse, some JavaScript served over insecure HTTPS...<br>
+
+
+</body>
+</html>
diff --git a/chrome/test/data/ssl/set_foo.js b/chrome/test/data/ssl/set_foo.js
new file mode 100644
index 0000000..2dbb5d12
--- /dev/null
+++ b/chrome/test/data/ssl/set_foo.js
@@ -0,0 +1 @@
+foo = "bar";
diff --git a/chrome/test/data/sync_xmlhttprequest.html b/chrome/test/data/sync_xmlhttprequest.html
new file mode 100644
index 0000000..cf3e8d6
--- /dev/null
+++ b/chrome/test/data/sync_xmlhttprequest.html
@@ -0,0 +1,32 @@
+<html>
+<head>
+<script>
+var request_success = false;
+
+function OnLoad() {
+ var request = new XMLHttpRequest();
+ request.open("GET", "title1.html", false);
+ request.send("");
+
+ var my_div = document.getElementById("my_div");
+ if (request.readyState == 4 && request.status == 200) {
+ request_success = true;
+ my_div.innerHTML = "Got a successful response: " + request.responseText;
+ } else {
+ my_div.innerHTML = "Request failed: ready state=" + request.readyState +
+ " status=" + request.status;
+ }
+}
+
+function DidSyncRequestSucceed() {
+ return request_success;
+}
+
+</script>
+</head>
+<body onload="OnLoad();">
+This page sends a synchronous XMLHttpRequest.
+<br><br>
+<div id="my_div"></div>
+</body>
+</html>
diff --git a/chrome/test/data/sync_xmlhttprequest_during_unload.html b/chrome/test/data/sync_xmlhttprequest_during_unload.html
new file mode 100644
index 0000000..6b726b1
--- /dev/null
+++ b/chrome/test/data/sync_xmlhttprequest_during_unload.html
@@ -0,0 +1,20 @@
+<html>
+ <head>
+ <title>Loading...</title>
+ </head>
+ <body onload="attachUnloadListener()">
+ <script>
+ function attachUnloadListener() {
+ window.addEventListener('unload', onUnload, false);
+ document.title = "sync xhr on unload";
+ }
+
+ var req = new XMLHttpRequest();
+ function onUnload() {
+ req.open('GET','download-test1.lib', false);
+ req.send(null);
+ }
+ </script>
+ <p>Navigate to another page to trigger synch xmlhttprequest</p>
+ </body>
+</html>
diff --git a/chrome/test/data/title1.html b/chrome/test/data/title1.html
new file mode 100644
index 0000000..2526072
--- /dev/null
+++ b/chrome/test/data/title1.html
@@ -0,0 +1,4 @@
+<html>
+<head></head>
+<body>This page has no title.</body>
+</html>
diff --git a/chrome/test/data/title2.html b/chrome/test/data/title2.html
new file mode 100644
index 0000000..13823c9
--- /dev/null
+++ b/chrome/test/data/title2.html
@@ -0,0 +1,4 @@
+<html>
+<head><title>Title Of Awesomeness</title></head>
+<body>This page has a title.</body>
+</html>
diff --git a/chrome/test/data/viewsource/test.html b/chrome/test/data/viewsource/test.html
new file mode 100644
index 0000000..f27bf2f
--- /dev/null
+++ b/chrome/test/data/viewsource/test.html
@@ -0,0 +1,11 @@
+<html>
+<head>
+<script>
+function setCookie() {
+ document.cookie = 'viewsource_cookie=foo';
+}
+</script>
+</head>
+<body onload="setCookie();">
+</body>
+</html>
diff --git a/chrome/test/data/window.close.html b/chrome/test/data/window.close.html
new file mode 100644
index 0000000..ebe16868
--- /dev/null
+++ b/chrome/test/data/window.close.html
@@ -0,0 +1,53 @@
+<script>
+var popup, popup2, popup3, popup4;
+
+// window.open, window.close should be synchronous
+function test1() {
+ popup = window.open('title1.html', 'name');
+ popup.close();
+
+ popup = window.open('title2.html', 'name', 'width=200,height=200');
+ popup.close();
+}
+
+// Try opening/closing a few windows.
+function test2() {
+ openPopups();
+ closePopups();
+}
+
+function test3() {
+ openPopups();
+ setTimeout(closePopups, 0);
+ setTimeout(test4, 1);
+}
+
+function test4() {
+ openPopups();
+ setTimeout(closePopupsAndDone, 250);
+}
+
+function openPopups() {
+ popup = window.open('title1.html', 'name');
+ popup2 = window.open('title1.html', 'name2');
+ popup3 = window.open('title1.html', 'name3');
+ popup4 = window.open('title1.html', 'name4');
+}
+
+function closePopups() {
+ popup.close();
+ popup2.close();
+ popup3.close();
+ popup4.close();
+}
+
+function closePopupsAndDone() {
+ closePopups();
+ document.title = "PASSED";
+}
+
+test1();
+test2();
+test3();
+
+</script>
diff --git a/chrome/test/debugger/debugger_unittests.py b/chrome/test/debugger/debugger_unittests.py
new file mode 100644
index 0000000..bacaa00
--- /dev/null
+++ b/chrome/test/debugger/debugger_unittests.py
@@ -0,0 +1,50 @@
+# debugger_unittests.py
+#
+# Run chrome debugger front-end tests.
+# see also chrome/test/debugger/test_protocol.js
+
+import optparse
+import os.path
+import subprocess
+import sys
+import time
+
+import google.path_utils
+import google.process_utils
+
+def RunTests(build_dir=None):
+ '''This is just a simple wrapper for running the test through v8_shell.
+ Since v8_shell always returns 0 whether the test passes or fails, buildbot
+ looks at stdout to test for failure.
+ '''
+ script_dir = google.path_utils.ScriptDir()
+ chrome_dir = google.path_utils.FindUpward(script_dir, "chrome")
+ v8_dir = google.path_utils.FindUpward(script_dir, "v8")
+ if build_dir:
+ v8_shell = os.path.join(build_dir, "v8_shell.exe")
+ else:
+ v8_shell = os.path.join(chrome_dir, "Debug", "v8_shell.exe")
+ # look for Debug version first
+ if not os.path.isfile(v8_shell):
+ v8_shell = os.path.join(chrome_dir, "Release", "v8_shell.exe")
+ cmd = [v8_shell,
+ "--allow-natives-syntax",
+ "--expose-debug-as", "debugContext", # these two are together
+ os.path.join(chrome_dir, "browser", "resources", "debugger_shell.js"),
+ os.path.join(v8_dir, "tests", "mjsunit.js"),
+ os.path.join(chrome_dir, "test", "debugger", "test_protocol.js")
+ ]
+ (retcode, output) = google.process_utils.RunCommandFull(cmd,
+ collect_output=True)
+ if "Success" in output:
+ return 0
+ else:
+ return 1
+
+if __name__ == "__main__":
+ parser = optparse.OptionParser("usage: %prog [--build_dir=dir]")
+ parser.add_option("", "--build_dir",
+ help="directory where v8_shell.exe was built")
+ (options, args) = parser.parse_args()
+ ret = RunTests(options.build_dir)
+ sys.exit(ret)
diff --git a/chrome/test/debugger/debugger_unittests.sh b/chrome/test/debugger/debugger_unittests.sh
new file mode 100755
index 0000000..443488d
--- /dev/null
+++ b/chrome/test/debugger/debugger_unittests.sh
@@ -0,0 +1,9 @@
+#!/bin/sh
+
+system_root=`cygpath "$SYSTEMROOT"`
+export PATH="/usr/bin:$system_root/system32:$system_root:$system_root/system32/WBEM"
+
+exec_dir=$(dirname $0)
+
+"$exec_dir/../../../third_party/python_24/python.exe" \
+ "$exec_dir/debugger_unittests.py" "$@"
diff --git a/chrome/test/debugger/test_protocol.js b/chrome/test/debugger/test_protocol.js
new file mode 100644
index 0000000..6ca0835
--- /dev/null
+++ b/chrome/test/debugger/test_protocol.js
@@ -0,0 +1,293 @@
+// Copyright 2008 Google Inc. All Rights Reserved.
+// test_protocol.js
+
+/**
+ * @fileoverview Unit tests for testing debugger protocol betweeen front-end JS
+ * and back-end.
+ * Run with the following command line:
+ * v8_shell.exe --allow-natives-syntax --expose-debug-as debugContext
+ * chrome/browser/resources/shell.js
+ * v8/tests/mjsunit.js
+ * chrome/test/debugger/test_protocol.js
+ */
+
+
+/**
+ * shell() is normally a native function exposed to shell.js in Chrome that
+ * sets the global DebugShell (shell_) object used for the debugger front-end.
+ */
+function shell(sh) {
+ shell_ = sh;
+ shell_.response("{type: 'event', event: 'attach'}");
+};
+
+
+/**
+ * @class The global chrome object has some functions to control some status UI
+ * in the debugger window. Stub them out here.
+ */
+function chrome() {
+};
+chrome.setDebuggerReady = function(ready) {};
+chrome.setDebuggerBreak = function(brk) {};
+
+
+/**
+ * @constructor a pseudo namespace to wrap the various functions and data for
+ * the test
+ */
+function DebuggerTest() {
+};
+
+/**
+ * initialize the member
+ */
+DebuggerTest.initialize = function() {
+ DebuggerTest.pendingCommand = null;
+ DebuggerTest.output = [];
+
+ // swap out the built-in print with our own so that we can verify output
+ DebuggerTest.realPrint = print;
+ print = DebuggerTest.print;
+ // uncomment this to see more verbose information
+ //dprint = DebuggerTest.realPrint;
+
+ debugContext.Debug.addListener(DebuggerTest.listener);
+};
+
+/**
+ * Collects calls to print() in an array for test verification.
+ */
+DebuggerTest.print = function(str) {
+ DebuggerTest.output.push(str);
+ // uncomment this if you need to trace what's happening while it's happening
+ // rather than waiting for the end
+ //DebuggerTest.realPrint(str);
+};
+
+/**
+ * Processes pendingCommand and sends response to shell_. Since that may in
+ * turn generate a new pendingCommand, repeat this until there is no
+ * pendingCommand.
+ */
+DebuggerTest.processCommands = function(dcp) {
+ while (DebuggerTest.pendingCommand) {
+ var json = DebuggerTest.pendingCommand;
+ DebuggerTest.pendingCommand = null;
+ var result = dcp.processDebugJSONRequest(json);
+ shell_.response(result);
+ }
+};
+
+/**
+ * Handles DebugEvents from the Debug object. Hooked in via addListener above.
+ */
+DebuggerTest.listener = function(event, exec_state, event_data, data) {
+ try {
+ if (event == debugContext.Debug.DebugEvent.Break) {
+ var dcp = exec_state.debugCommandProcessor();
+ // process any pending commands prior to handling the breakpoint
+ DebuggerTest.processCommands(dcp);
+ var json = event_data.toJSONProtocol();
+ shell_.response(json);
+ // response() may have added another command to process
+ DebuggerTest.processCommands(dcp);
+ }
+ } catch(e) {
+ print(e);
+ }
+};
+
+/**
+ * Send the next command from the command-list.
+ */
+DebuggerTest.sendNextCommand = function() {
+ var cmd = DebuggerTest.commandList.shift();
+ print("$ " + cmd);
+ shell_.command(cmd);
+};
+
+/**
+ * Verify that the actual output matches the expected output
+ * depends on mjsunit
+ */
+DebuggerTest.verifyOutput = function() {
+ // restore print since mjsunit depends on it
+ print = DebuggerTest.realPrint;
+
+ var out = DebuggerTest.output;
+ var expected = DebuggerTest.expectedOutput;
+ if (out.length != expected.length) {
+ assertTrue(out.length == expected.length,
+ "length mismatch: " + out.length + " == " + expected.length);
+ } else {
+ var succeeded = true;
+ for (var i in out) {
+ // match the front of the string so we can avoid testing changes in frames
+ // that are in the test harness
+ if (out[i].indexOf(expected[i]) != 0) {
+ assertTrue(out[i] == expected[i],
+ "actual '" + out[i] + "' == " + "expected '" + expected[i] + "'");
+ succeeded = false;
+ break;
+ }
+ }
+ if (succeeded)
+ print("Success");
+ }
+
+ // useful for generating a new version of DebuggerTest.expectedOutput
+ for (var i in DebuggerTest.output) {
+ //print(" \"" + DebuggerTest.output[i] + "\",");
+ }
+};
+
+
+
+/**
+ * @class DebugShell is passed a "Tab" object that it uses to communicate with
+ * the debugger. This mock simulates that.
+ * @param {string} title
+ */
+DebuggerTest.TabMock = function(title) {
+ this.title = title;
+ this.attach = function() {};
+ this.debugBreak = function() {
+ // TODO(erikkay)
+ };
+ this.sendToDebugger = function(str) {
+ DebuggerTest.pendingCommand = str;
+ };
+};
+
+
+/**
+ * @class Uses prototype chaining to allow DebugShell methods to be overridden
+ * selectively.
+ */
+function DebugShellOverrides() {
+ this._origPrototype = DebugShell.prototype;
+};
+DebugShellOverrides.prototype = DebugShell.prototype;
+DebugShell.prototype = new DebugShellOverrides;
+
+/**
+ * Overrides DebugShell.prototype.response so that we can log the responses
+ * and trigger the next command to be processed.
+ */
+DebugShell.prototype.response = function(str) {
+ var msg = eval('(' + str + ')');
+ print("< " + msg.type + ":" + (msg.command || msg.event));
+ var sendAnother = (msg.type == "event");
+ if (!sendAnother && shell_.current_command) {
+ sendAnother = (shell_.current_command.from_user &&
+ msg.type == "response" && msg.command != "continue")
+ }
+ this._origPrototype.response.call(this, str)
+
+ // Send the next command, but only if the program is paused (a continue
+ // command response means that we're about to be running again) and the
+ // command we just processed isn't a continue
+ if (!this.running && sendAnother)
+ DebuggerTest.sendNextCommand();
+};
+
+
+// The list of commands to be processed
+// TODO(erikkay): this doesn't test the full set of debugger commands yet,
+// but it should be enough to verify that the protocol is still working.
+DebuggerTest.commandList = [
+"next", "step", "backtrace", "source", "print x", "args", "locals", "frame 1",
+"stepout", "continue"
+];
+
+DebuggerTest.expectedOutput = [
+ "< event:attach",
+ "attached to testing",
+ "< response:scripts",
+ "< event:break",
+ "g(), foo.html",
+ "60: debugger;",
+ "$ next",
+ "< response:continue",
+ "< event:break",
+ "61: f(1);",
+ "$ step",
+ "< response:continue",
+ "< event:break",
+ "f(x=1, y=undefined), foo.html",
+ "29: return a;",
+ "$ backtrace",
+ "< response:backtrace",
+ "Frames #0 to #3 of 4:",
+ "#00 f(x=1, y=undefined) foo.html line 29 column 3 (position 62)",
+ "#01 g() foo.html line 61 column 3 (position 30)",
+ "#02 function DebuggerTest()", // prefix
+ "#03 [anonymous]()", // prefix
+ "$ source",
+ "< response:source",
+ "24: function f(x, y) {",
+ "25: var a=1;",
+ "26: if (x == 1) {",
+ "27: a++;",
+ "28: }",
+ ">>>> return a;",
+ "30: };",
+ "$ print x",
+ "< response:evaluate",
+ "1",
+ "$ args",
+ "< response:frame",
+ "x = 1",
+ "y = undefined",
+ "$ locals",
+ "< response:frame",
+ "a = 2",
+ "$ frame 1",
+ "< response:frame",
+ "#1 g, foo.html",
+ "61: f(1);",
+ "$ stepout",
+ "< response:continue",
+ "< event:break",
+ "g(), foo.html",
+ "62: };",
+ "$ continue",
+ "< response:continue"
+];
+
+
+/**
+ * Tests the debugger and protocol for a couple of simple scripts.
+ */
+DebuggerTest.testProtocol = function() {
+ DebuggerTest.initialize();
+
+ // Startup the front-end.
+ debug(new DebuggerTest.TabMock("testing"));
+
+ script1 =
+ "function f(x, y) {\n" + // line 23
+ " var a=1;\n" + // line 24
+ " if (x == 1) {\n" + // line 25
+ " a++;\n }\n" + // line 26
+ " return a;\n" + // line 27
+ "};"; // line 28
+ script2 =
+ "function g() {\n" + // line 58
+ " debugger;\n" + // line 59
+ " f(1);\n" + // line 60
+ "};"; // line 61
+ %CompileScript(script1, "foo.html", 23, 0)();
+ %CompileScript(script2, "foo.html", 58, 0)();
+
+ try {
+ g();
+ } catch(e) {
+ print(e);
+ }
+
+ DebuggerTest.verifyOutput();
+}
+
+DebuggerTest.testProtocol();
diff --git a/chrome/test/injection_test_dll.h b/chrome/test/injection_test_dll.h
new file mode 100644
index 0000000..a3dce18
--- /dev/null
+++ b/chrome/test/injection_test_dll.h
@@ -0,0 +1,51 @@
+// 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.
+
+#ifndef CHROME_TEST_INJECTION_TEST_DLL_H__
+#define CHROME_TEST_INJECTION_TEST_DLL_H__
+
+// This file defines the entry points for any DLL that can be loaded into the
+// renderer or plugin process for the purposes of testing. The DLL code must
+// define TEST_INJECTION_DLL so the entry point definitions cause the linker
+// to generate exported functions.
+
+const char kRenderTestCall[] = "RunRendererTests";
+const char kPluginTestCall[] = "RunPluginTests";
+
+extern "C" {
+#ifdef TEST_INJECTION_DLL
+BOOL extern __declspec(dllexport) __cdecl RunRendererTests(int* test_count);
+BOOL extern __declspec(dllexport) __cdecl RunPluginTests(int* test_count);
+#else
+typedef BOOL (__cdecl *RunRendererTests)(int* test_count);
+typedef BOOL (__cdecl *RunPluginTests)(int* test_count);
+#endif
+}
+
+#endif // CHROME_TEST_INJECTION_TEST_DLL_H__
diff --git a/chrome/test/interactive_ui/SConscript b/chrome/test/interactive_ui/SConscript
new file mode 100644
index 0000000..db4fddb
--- /dev/null
+++ b/chrome/test/interactive_ui/SConscript
@@ -0,0 +1,132 @@
+# 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.
+
+Import('env_test')
+
+env_test = env_test.Clone()
+
+
+env_test.Prepend(
+ CPPDEFINES = [
+ 'UI_TEST',
+ 'UNIT_TEST',
+ 'LIBXSLT_STATIC',
+ 'LIBXML_STATIC',
+ 'CERT_CHAIN_PARA_HAS_EXTRA_FIELDS',
+ 'WIN32_LEAN_AND_MEAN',
+ ],
+ CPPPATH = [
+ '$GTEST_DIR/include',
+ '$GTEST_DIR',
+ '$SKIA_DIR/include',
+ '$SKIA_DIR/include/corecg',
+ '$SKIA_DIR/platform',
+ '#/..',
+ '$CHROME_DIR/third_party/wtl/include',
+ '$LIBXSLT_DIR',
+ '$LIBXML_DIR/include',
+ ],
+ LINKFLAGS = [
+ '/INCREMENTAL',
+ '/DEBUG',
+
+ '/DELAYLOAD:"dwmapi.dll"',
+ '/DELAYLOAD:"uxtheme.dll"',
+
+ '/MACHINE:X86',
+ '/FIXED:No',
+
+ '/safeseh',
+ '/dynamicbase',
+ '/ignore:4199',
+ '/nxcompat',
+ ],
+ LIBS = [
+ 'winmm.lib',
+ 'psapi.lib',
+ 'rpcrt4.lib',
+ 'oleacc.lib',
+ 'comsupp.lib',
+
+ 'wininet.lib',
+ 'version.lib',
+ 'msimg32.lib',
+ 'ws2_32.lib',
+ 'usp10.lib',
+ 'psapi.lib',
+ 'kernel32.lib',
+ 'user32.lib',
+ 'gdi32.lib',
+ 'winspool.lib',
+ 'comdlg32.lib',
+ 'advapi32.lib',
+ 'shell32.lib',
+ 'ole32.lib',
+ 'oleaut32.lib',
+ 'uuid.lib',
+ 'odbc32.lib',
+ 'odbccp32.lib',
+
+ 'DelayImp.lib',
+ ],
+)
+
+input_files = [
+ '$CHROME_DIR/browser/browser_focus_uitest.cc',
+ '$CHROME_DIR/browser/views/constrained_window_impl_interactive_uitest.cc',
+ '$CHROME_DIR/test/ui/run_all_unittests$OBJSUFFIX',
+ '$CHROME_DIR/test/ui/ui_test$OBJSUFFIX',
+ '$CHROME_DIR/test/ui/ui_test_suite$OBJSUFFIX',
+ '$CHROME_DIR/test/test_file_util$OBJSUFFIX',
+]
+
+libs = [
+ '$GOOGLEURL_DIR/googleurl.lib',
+ '$SKIA_DIR/skia.lib',
+ '$LIBPNG_DIR/libpng.lib',
+ '$TESTING_DIR/gtest.lib',
+ '$BASE_DIR/gfx/base_gfx.lib',
+ '$ICU38_DIR/icuuc.lib',
+ '$CHROME_DIR/common/common.lib',
+ '$ZLIB_DIR/zlib.lib',
+ '$MODP_B64_DIR/modp_b64.lib',
+ '$CHROME_DIR/browser/browser.lib',
+ '$NET_DIR/net.lib',
+ '$BZIP2_DIR/bzip2.lib',
+ '$BASE_DIR/base.lib',
+ '$CHROME_DIR/test/automation/automation.lib',
+]
+
+
+exe = env_test.Program(['interactive_ui_tests',
+ 'interactive_ui_tests.pdb'],
+ input_files + libs)
+i = env_test.Install('$TARGET_ROOT', exe)
+
+env_test.Alias('chrome', i)
diff --git a/chrome/test/interactive_ui/interactive_ui.vcproj b/chrome/test/interactive_ui/interactive_ui.vcproj
new file mode 100644
index 0000000..56c649f
--- /dev/null
+++ b/chrome/test/interactive_ui/interactive_ui.vcproj
@@ -0,0 +1,197 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="interactive_ui_tests"
+ ProjectGUID="{018D4F38-6272-448F-A864-976DA09F05D0}"
+ RootNamespace="manual_ui"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ ConfigurationType="1"
+ InheritedPropertySheets="$(SolutionDir)..\build\common.vsprops;$(SolutionDir)..\build\debug.vsprops;..\..\tools\build\win\precompiled_wtl.vsprops;$(SolutionDir)..\third_party\libxml\build\using_libxml.vsprops;$(SolutionDir)..\third_party\libxslt\build\using_libxslt.vsprops;..\..\tools\build\win\unit_test.vsprops;..\..\tools\build\win\ui_test.vsprops;$(SolutionDir)..\skia\using_skia.vsprops;$(SolutionDir)..\testing\using_gtest.vsprops"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ />
+ <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"
+ ConfigurationType="1"
+ InheritedPropertySheets="$(SolutionDir)..\build\common.vsprops;$(SolutionDir)..\build\release.vsprops;$(SolutionDir)..\third_party\libxml\build\using_libxml.vsprops;$(SolutionDir)..\third_party\libxslt\build\using_libxslt.vsprops;..\..\tools\build\win\unit_test.vsprops;..\..\tools\build\win\ui_test.vsprops;$(SolutionDir)..\skia\using_skia.vsprops;$(SolutionDir)..\testing\using_gtest.vsprops"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="winmm.lib"
+ />
+ <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="Common"
+ >
+ <File
+ RelativePath="..\..\tools\build\win\precompiled_wtl.cc"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="1"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\tools\build\win\precompiled_wtl.h"
+ >
+ </File>
+ <File
+ RelativePath="..\ui\run_all_unittests.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\test_file_util.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\ui\ui_test.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\ui\ui_test.h"
+ >
+ </File>
+ <File
+ RelativePath="..\ui\ui_test_suite.cc"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="TestFocus"
+ >
+ <File
+ RelativePath="..\..\browser\browser_focus_uitest.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\browser\views\constrained_window_impl_interactive_uitest.cc"
+ >
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/chrome/test/mini_installer_test/SConscript b/chrome/test/mini_installer_test/SConscript
new file mode 100644
index 0000000..6a474f0
--- /dev/null
+++ b/chrome/test/mini_installer_test/SConscript
@@ -0,0 +1,111 @@
+# 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.
+
+Import('env_test')
+
+
+env_test = env_test.Clone()
+
+
+env_test.Prepend(
+ CPPDEFINES = [
+ 'UNIT_TEST',
+ 'CERT_CHAIN_PARA_HAS_EXTRA_FIELDS',
+ 'WIN32_LEAN_AND_MEAN',
+ ],
+ CPPPATH = [
+ '$GTEST_DIR/include',
+ '$GTEST_DIR',
+ '#/..',
+ ],
+ LINKFLAGS = [
+ '/INCREMENTAL',
+ '/DEBUG',
+
+ '/DELAYLOAD:"dwmapi.dll"',
+ '/DELAYLOAD:"uxtheme.dll"',
+
+ '/MACHINE:X86',
+ '/FIXED:No',
+
+ '/safeseh',
+ '/dynamicbase',
+ '/ignore:4199',
+ '/nxcompat',
+ ],
+ LIBS = [
+ 'shlwapi.lib',
+ 'rpcrt4.lib',
+ 'oleacc.lib',
+ 'comsupp.lib',
+
+ 'wininet.lib',
+ 'version.lib',
+ 'msimg32.lib',
+ 'ws2_32.lib',
+ 'usp10.lib',
+ 'psapi.lib',
+ 'kernel32.lib',
+ 'user32.lib',
+ 'gdi32.lib',
+ 'winspool.lib',
+ 'comdlg32.lib',
+ 'advapi32.lib',
+ 'shell32.lib',
+ 'ole32.lib',
+ 'oleaut32.lib',
+ 'uuid.lib',
+ 'odbc32.lib',
+ 'odbccp32.lib',
+
+ 'DelayImp.lib',
+ ],
+)
+
+input_files = [
+ '$CHROME_DIR/installer/setup/setup_constants$OBJSUFFIX',
+ '$CHROME_DIR/installer/util/run_all_unittests$OBJSUFFIX',
+ 'chrome_mini_installer.cc',
+ 'mini_installer_test_constants.cc',
+ 'test.cc',
+]
+
+libs = [
+ '$CHROME_DIR/installer/util/util.lib',
+ '$TESTING_DIR/gtest.lib',
+ '$ICU38_DIR/icuuc.lib',
+ '$BASE_DIR/base.lib',
+]
+
+exe = env_test.Program(['mini_installer_test',
+ 'mini_installer_test.pdb'],
+ input_files + libs)
+i = env_test.Install('$TARGET_ROOT', exe)
+
+env_test.Alias('chrome', i)
diff --git a/chrome/test/mini_installer_test/chrome_mini_installer.cc b/chrome/test/mini_installer_test/chrome_mini_installer.cc
new file mode 100644
index 0000000..c8d67c3
--- /dev/null
+++ b/chrome/test/mini_installer_test/chrome_mini_installer.cc
@@ -0,0 +1,310 @@
+// 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.
+
+#include "chrome/test/mini_installer_test/chrome_mini_installer.h"
+
+#include "base/path_service.h"
+#include "base/process_util.h"
+#include "base/registry.h"
+#include "base/string_util.h"
+#include "chrome/installer/setup/setup_constants.h"
+#include "chrome/installer/util/install_util.h"
+#include "chrome/installer/util/google_update_constants.h"
+#include "chrome/installer/util/util_constants.h"
+#include "chrome/test/mini_installer_test/mini_installer_test_constants.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+// Installs the Chrome mini-installer, checks the registry and shortcuts.
+void ChromeMiniInstaller::InstallMiniInstaller(bool over_install) {
+ // If need to do clean installation, uninstall chrome if exists.
+ if (!over_install) {
+ UnInstall();
+ }
+ LaunchExe(mini_installer_constants::kChromeMiniInstallerExecutable,
+ mini_installer_constants::kChromeMiniInstallerExecutable);
+ ASSERT_TRUE(CheckRegistryKey(InstallUtil::GetChromeGoogleUpdateKey()));
+ FindChromeShortcut();
+ WaitUntilProcessStartsRunning(installer_util::kChromeExe);
+ if (!over_install) {
+ ASSERT_TRUE(CloseWindow(
+ mini_installer_constants::kFirstChromeUI, WM_CLOSE));
+ } else {
+ ASSERT_TRUE(CloseWindow(
+ mini_installer_constants::kBrowserTabName, WM_CLOSE));
+ }
+ VerifyChromeLaunch();
+}
+
+// Installs chromesetupdev.exe, waits for the install to finish and then
+// checks the registry and shortcuts.
+void ChromeMiniInstaller::InstallChromeSetupDev() {
+ // Uninstall chrome, if already installed.
+ UnInstall();
+
+ // Install older/dev version of chrome.
+ LaunchExe(mini_installer_constants::kChromeSetupDevExeLocation,
+ mini_installer_constants::kChromeSetupExecutable);
+ WaitUntilProcessStopsRunning(
+ mini_installer_constants::kChromeMiniInstallerExecutable);
+ std::wstring chrome_google_update_state_key(
+ google_update::kRegPathClientState);
+ chrome_google_update_state_key.append(L"\\");
+ chrome_google_update_state_key.append(google_update::kChromeGuid);
+ ASSERT_TRUE(CheckRegistryKey(chrome_google_update_state_key));
+ ASSERT_TRUE(CheckRegistryKey(InstallUtil::GetChromeGoogleUpdateKey()));
+ FindChromeShortcut();
+ WaitUntilProcessStartsRunning(installer_util::kChromeExe);
+ ASSERT_TRUE(CloseWindow(mini_installer_constants::kFirstChromeUI, WM_CLOSE));
+}
+
+// Accepts mini/dev as parameters. If mini, installs mini_installer first.
+// if dev, installs ChromeSetupDev.exe first and
+// then over installs with mini_installer.
+// Also, verifies if Chrome can be launched sucessfully after overinstall.
+void ChromeMiniInstaller::OverInstall() {
+ InstallChromeSetupDev();
+ // gets the registry key value before overinstall.
+ std::wstring reg_key_value_returned = GetRegistryKey();
+ printf("\n\nPreparing to overinstall...\n");
+ printf("\nOverinstall path is %ls\n",
+ mini_installer_constants::kChromeMiniInstallerExecutable);
+ InstallMiniInstaller(true);
+ // Get the registry key value after over install
+ std::wstring reg_key_value_after_overinstall = GetRegistryKey();
+ ASSERT_TRUE(VerifyOverInstall(
+ reg_key_value_returned, reg_key_value_after_overinstall));
+}
+
+// This method first checks if Chrome is running.
+// If yes, will close all the processes.
+// Then will find and spawn uninstall path.
+// Handles uninstall confirm dialog.
+// Waits until setup.exe ends.
+// Checks if registry key exist even after uninstall.
+// Deletes App dir.
+void ChromeMiniInstaller::UnInstall() {
+ printf("Verifying if Chrome is installed...\n");
+ if (!CheckRegistryKey(InstallUtil::GetChromeGoogleUpdateKey())) {
+ printf("Chrome is not installed.\n");
+ return;
+ }
+
+ printf("\nClosing Chrome processes, if any...\n");
+ CloseChromeProcesses();
+
+ std::wstring uninstall_path = GetUninstallPath();
+ ASSERT_TRUE(file_util::PathExists(uninstall_path));
+
+ printf("\nUninstalling Chrome...\n");
+ process_util::LaunchApp(L"\"" + uninstall_path + L"\"" + L" -uninstall",
+ false, false, NULL);
+ printf("\nLaunched setup.exe -uninstall....\n");
+ ASSERT_TRUE(CloseWindow(
+ mini_installer_constants::kConfirmDialog, WM_COMMAND));
+ WaitUntilProcessStopsRunning(
+ mini_installer_constants::kChromeSetupExecutable);
+ ASSERT_FALSE(CheckRegistryKey(InstallUtil::GetChromeGoogleUpdateKey()));
+ DeleteAppFolder();
+ FindChromeShortcut();
+ if (false == CloseWindow(mini_installer_constants::kChromeUninstallIETitle,
+ WM_CLOSE)) {
+ printf("\nFailed to close window \"%s\".",
+ mini_installer_constants::kChromeUninstallIETitle);
+ }
+}
+
+// Takes care of Chrome uninstall dialog.
+bool ChromeMiniInstaller::CloseWindow(LPCWSTR window_name, UINT message) {
+ int timer = 0;
+ bool return_val = false;
+ HWND hndl = FindWindow(NULL, window_name);
+ while (hndl== NULL && (timer < 60000)) {
+ hndl = FindWindow(NULL, window_name);
+ Sleep(200);
+ timer = timer + 200;
+ }
+ if (hndl != NULL) {
+ LRESULT _result = SendMessage(hndl, message, 1, 0);
+ return_val = true;
+ }
+ return return_val;
+}
+
+// Closes Chrome browser.
+void ChromeMiniInstaller::CloseChromeBrowser(LPCWSTR window_name) {
+ WaitUntilProcessStartsRunning(installer_util::kChromeExe);
+ ASSERT_TRUE(CloseWindow(window_name, WM_CLOSE));
+}
+
+// Checks for all running Chrome processes and kills them.
+void ChromeMiniInstaller::CloseChromeProcesses() {
+ int timer = 0;
+ while ((process_util::GetProcessCount(installer_util::kChromeExe, NULL) > 0) &&
+ (timer < 20000)) {
+ process_util::KillProcesses(installer_util::kChromeExe, 1, NULL);
+ Sleep(200);
+ timer = timer + 200;
+ }
+ ASSERT_EQ(0, process_util::GetProcessCount(installer_util::kChromeExe, NULL));
+}
+
+// Checks for Chrome registry keys.
+bool ChromeMiniInstaller::CheckRegistryKey(std::wstring key_path) {
+ RegKey key;
+ if (!key.Open(HKEY_CURRENT_USER, key_path.c_str(), KEY_ALL_ACCESS)) {
+ printf("Cannot open reg key\n");
+ return false;
+ }
+ std::wstring reg_key_value_returned = GetRegistryKey();
+ printf("Reg key value is%ls\n", reg_key_value_returned.c_str());
+ return true;
+}
+
+// Deletes App folder after uninstall.
+void ChromeMiniInstaller::DeleteAppFolder() {
+ std::wstring path;
+ ASSERT_TRUE(PathService::Get(base::DIR_LOCAL_APP_DATA, &path));
+ file_util::AppendToPath(&path, mini_installer_constants::kAppDir);
+ file_util::UpOneDirectory(&path);
+ printf("Deleting this path after uninstall%ls\n", path.c_str());
+ ASSERT_TRUE(file_util::Delete(path.c_str(), true));
+}
+
+// Verifies if Chrome shortcut exists.
+void ChromeMiniInstaller::FindChromeShortcut() {
+ std::wstring username, path_name, append_path, uninstall_lnk, shortcut_path;
+ bool return_val = false;
+ ASSERT_TRUE(PathService::Get(base::DIR_START_MENU, &path_name));
+ file_util::AppendToPath(&path_name, L"Google Chrome");
+ // Verify if path exists.
+ if (file_util::PathExists(path_name)) {
+ return_val = true;
+ uninstall_lnk = path_name;
+ file_util::AppendToPath(&path_name, L"Google Chrome.lnk");
+ file_util::AppendToPath(&uninstall_lnk, L"Uninstall Google Chrome.lnk");
+ ASSERT_TRUE(file_util::PathExists(path_name));
+ ASSERT_TRUE(file_util::PathExists(uninstall_lnk));
+ }
+ if (return_val)
+ printf("Chrome shortcuts found are:\n%ls\n%ls\n",
+ path_name.c_str(), uninstall_lnk.c_str());
+ else
+ printf("Chrome shortcuts not found\n");
+}
+
+// Gets the path for uninstall.
+std::wstring ChromeMiniInstaller::GetUninstallPath() {
+ std::wstring username, append_path, path;
+ std::wstring build_key_value = GetRegistryKey();
+ PathService::Get(base::DIR_LOCAL_APP_DATA, &path);
+ file_util::AppendToPath(&path, mini_installer_constants::kAppDir);
+ file_util::AppendToPath(&path, build_key_value);
+ file_util::AppendToPath(&path, installer::kInstallerDir);
+ file_util::AppendToPath(&path,
+ mini_installer_constants::kChromeSetupExecutable);
+ printf("uninstall path is %ls\n", path.c_str());
+ return path;
+}
+
+// Reads Chrome registry key.
+std::wstring ChromeMiniInstaller::GetRegistryKey() {
+ std::wstring build_key_value;
+ RegKey key(HKEY_CURRENT_USER, InstallUtil::GetChromeGoogleUpdateKey().c_str());
+ if (!key.ReadValue(L"pv", &build_key_value))
+ return false;
+ return build_key_value;
+}
+
+// Launches a given executable and waits until it is done.
+void ChromeMiniInstaller::LaunchExe(std::wstring path,
+ const wchar_t process_name[]) {
+ printf("\nBuild to be installed is: %ls\n", path.c_str());
+ ASSERT_TRUE(file_util::PathExists(path));
+ process_util::LaunchApp(L"\"" + path + L"\"", false, false, NULL);
+ printf("Waiting while this process is running %ls ....", process_name);
+ WaitUntilProcessStartsRunning(process_name);
+ WaitUntilProcessStopsRunning(process_name);
+}
+
+// Launch Chrome to see if it works after overinstall. Then close it.
+void ChromeMiniInstaller::VerifyChromeLaunch() {
+ std::wstring username, path, append_path;
+ ASSERT_TRUE(PathService::Get(base::DIR_LOCAL_APP_DATA, &path));
+ file_util::AppendToPath(&path,
+ mini_installer_constants::kAppDir);
+ file_util::AppendToPath(&path, installer_util::kChromeExe);
+ process_util::LaunchApp(L"\"" + path + L"\"", false, false, NULL);
+ WaitUntilProcessStartsRunning(installer_util::kChromeExe);
+ Sleep(1200);
+}
+
+// This method compares the registry keys after overinstall.
+bool ChromeMiniInstaller::VerifyOverInstall(
+ std::wstring value_before_overinstall,
+ std::wstring value_after_overinstall) {
+ int64 reg_key_value_before_overinstall = StringToInt64(
+ value_before_overinstall);
+ int64 reg_key_value_after_overinstall = StringToInt64(
+ value_after_overinstall);
+ // Compare to see if the version is less.
+ printf("Reg Key value before overinstall is%ls\n",
+ value_before_overinstall.c_str());
+ printf("Reg Key value after overinstall is%ls\n",
+ value_after_overinstall.c_str());
+ if (reg_key_value_before_overinstall > reg_key_value_after_overinstall) {
+ printf("FAIL: Overinstalled a lower version of Chrome\n");
+ return false;
+ }
+ return true;
+}
+
+// Waits until the process starts running.
+void ChromeMiniInstaller::WaitUntilProcessStartsRunning(
+ const wchar_t process_name[]) {
+ int timer = 0;
+ while ((process_util::GetProcessCount(process_name, NULL) == 0) &&
+ (timer < 60000)) {
+ Sleep(200);
+ timer = timer + 200;
+ }
+ ASSERT_NE(0, process_util::GetProcessCount(process_name, NULL));
+}
+
+// Waits until the process stops running.
+void ChromeMiniInstaller::WaitUntilProcessStopsRunning(
+ const wchar_t process_name[]) {
+ int timer = 0;
+ printf("\nWaiting for this process to end... %ls\n", process_name);
+ while ((process_util::GetProcessCount(process_name, NULL) > 0) &&
+ (timer < 60000)) {
+ Sleep(200);
+ timer = timer + 200;
+ }
+ ASSERT_EQ(0, process_util::GetProcessCount(process_name, NULL));
+}
diff --git a/chrome/test/mini_installer_test/chrome_mini_installer.h b/chrome/test/mini_installer_test/chrome_mini_installer.h
new file mode 100644
index 0000000..27d5923
--- /dev/null
+++ b/chrome/test/mini_installer_test/chrome_mini_installer.h
@@ -0,0 +1,105 @@
+// 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.
+
+#ifndef CHROME_TEST_MINI_INSTALLER_TEST_CHROME_MINI_INSTALLER_H__
+#define CHROME_TEST_MINI_INSTALLER_TEST_CHROME_MINI_INSTALLER_H__
+
+#include <windows.h>
+#include <process.h>
+#include <psapi.h>
+#include <tlhelp32.h>
+#include <tchar.h>
+#include <errno.h>
+#include <string>
+
+#include "base/file_util.h"
+
+// This class has methods to install and uninstall Chrome mini installer.
+class ChromeMiniInstaller {
+ public:
+ ChromeMiniInstaller() {}
+ ~ChromeMiniInstaller() {}
+
+ // Installs Chrome Mini Installer.
+ void InstallMiniInstaller(bool over_install = false);
+
+ // Installs ChromeSetupDev.exe.
+ void InstallChromeSetupDev();
+
+ // This method takes care of all overinstall cases.
+ void OverInstall();
+
+ // Uninstalls Chrome.
+ void UnInstall();
+
+ // Verifies if Chrome launches after overinstall.
+ void VerifyChromeLaunch();
+
+ private:
+ // Closes Chrome uninstall confirm dialog window.
+ bool CloseWindow(LPCWSTR window_name, UINT message);
+
+ // Closes Chrome browser.
+ void CloseChromeBrowser(LPCWSTR window_name);
+
+ // Closes all running Chrome processes.
+ void CloseChromeProcesses();
+
+ // Checks for registry key.
+ bool CheckRegistryKey(std::wstring key_path);
+
+ // Deletes App folder after uninstall.
+ void DeleteAppFolder();
+
+ // This method verifies Chrome shortcut.
+ void FindChromeShortcut();
+
+ // Get path for uninstall.
+ std::wstring GetUninstallPath();
+
+ // Reads registry key.
+ std::wstring GetRegistryKey();
+
+ // Launches the given EXE and waits for it to end.
+ void LaunchExe(std::wstring install_path, const wchar_t process_name[]);
+
+ // Compares the registry key values after overinstall.
+ bool VerifyOverInstall(std::wstring reg_key_value_before_overinstall,
+ std::wstring reg_key_value_after_overinstall);
+
+ // Waits until the given process starts running
+ void WaitUntilProcessStartsRunning(const wchar_t process_name[]);
+
+ // Waits until the given process stops running
+ void WaitUntilProcessStopsRunning(const wchar_t process_name[]);
+
+ DISALLOW_EVIL_CONSTRUCTORS(ChromeMiniInstaller);
+};
+
+#endif // CHROME_TEST_MINI_INSTALLER_TEST_CHROME_MINI_INSTALLER_H__
diff --git a/chrome/test/mini_installer_test/mini_installer_test.vcproj b/chrome/test/mini_installer_test/mini_installer_test.vcproj
new file mode 100644
index 0000000..2a20087
--- /dev/null
+++ b/chrome/test/mini_installer_test/mini_installer_test.vcproj
@@ -0,0 +1,176 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="mini_installer_test"
+ ProjectGUID="{4B6E199A-034A-49BD-AB93-458DD37E45B1}"
+ RootNamespace="mini_installer_test"
+ Keyword="Win32Proj"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ ConfigurationType="1"
+ InheritedPropertySheets="$(SolutionDir)..\build\common.vsprops;$(SolutionDir)..\build\debug.vsprops;$(SolutionDir)\tools\build\win\unit_test.vsprops;$(SolutionDir)\installer\util\using_util.vsprops;$(SolutionDir)..\testing\using_gtest.vsprops"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ IgnoreDefaultLibraryNames=""
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ AdditionalManifestFiles="$(SolutionDir)installer\mini_installer\mini_installer.exe.manifest"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ ConfigurationType="1"
+ InheritedPropertySheets="$(SolutionDir)..\build\common.vsprops;$(SolutionDir)..\build\release.vsprops;$(SolutionDir)\tools\build\win\unit_test.vsprops;$(SolutionDir)\installer\util\using_util.vsprops;$(SolutionDir)..\testing\using_gtest.vsprops"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ AdditionalManifestFiles="$(SolutionDir)installer\mini_installer\mini_installer.exe.manifest"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <File
+ RelativePath=".\chrome_mini_installer.cc"
+ >
+ </File>
+ <File
+ RelativePath=".\chrome_mini_installer.h"
+ >
+ </File>
+ <File
+ RelativePath=".\mini_installer_test_constants.cc"
+ >
+ </File>
+ <File
+ RelativePath=".\mini_installer_test_constants.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\installer\util\run_all_unittests.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\installer\setup\setup_constants.cc"
+ >
+ </File>
+ <File
+ RelativePath=".\test.cc"
+ >
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/chrome/test/mini_installer_test/mini_installer_test_constants.cc b/chrome/test/mini_installer_test/mini_installer_test_constants.cc
new file mode 100644
index 0000000..d3f91be
--- /dev/null
+++ b/chrome/test/mini_installer_test/mini_installer_test_constants.cc
@@ -0,0 +1,51 @@
+// 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.
+
+#include "chrome/test/mini_installer_test/mini_installer_test_constants.h"
+
+namespace mini_installer_constants {
+
+const wchar_t kAppDir[] = L"Google\\Chrome\\Application\\";
+const wchar_t kChromeSetupExecutable[] = L"setup.exe";
+const wchar_t kChromeMiniInstallerExecutable[] = L"mini_installer.exe";
+const wchar_t kChromeInstallerType[] = L"dev";
+
+const wchar_t kBrowserAppName[] = L"Google - Google Chrome";
+const wchar_t kBrowserTabName[] = L"New Tab - Google Chrome";
+const wchar_t kConfirmDialog[] = L"Google Chrome";
+const wchar_t kInstallerWindow[] = L"Google App Installer";
+const wchar_t kFirstChromeUI[] = L"Welcome to Chrome";
+
+const wchar_t kChromeUninstallIETitle[] =
+ L"Google Chrome - Windows Internet Explorer";
+
+// Chrome meta installer location.
+const wchar_t kChromeSetupDevExeLocation[] =
+ L"\\\\172.23.44.61\\shared\\chrome_autotest\\DevTest\\ChromeSetup_en.exe";
+}
diff --git a/chrome/test/mini_installer_test/mini_installer_test_constants.h b/chrome/test/mini_installer_test/mini_installer_test_constants.h
new file mode 100644
index 0000000..d35c733
--- /dev/null
+++ b/chrome/test/mini_installer_test/mini_installer_test_constants.h
@@ -0,0 +1,54 @@
+// 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.
+
+// Constants related to the Chrome mini installer testing.
+
+#ifndef CHROME_TEST_MINI_INSTALLER_TEST_MINI_INSTALLER_TEST_CONSTANTS_H__
+#define CHROME_TEST_MINI_INSTALLER_TEST_MINI_INSTALLER_TEST_CONSTANTS_H__
+
+namespace mini_installer_constants {
+
+extern const wchar_t kAppDir[];
+extern const wchar_t kChromeSetupExecutable[];
+extern const wchar_t kChromeMiniInstallerExecutable[];
+extern const wchar_t kChromeInstallerType[];
+
+// Window names.
+extern const wchar_t kBrowserAppName[];
+extern const wchar_t kBrowserTabName[];
+extern const wchar_t kConfirmDialog[];
+extern const wchar_t kInstallerWindow[];
+extern const wchar_t kFirstChromeUI[];
+extern const wchar_t kChromeUninstallIETitle[];
+
+// Chrome meta installer location.
+extern const wchar_t kChromeSetupDevExeLocation[];
+}
+
+#endif // CHROME_TEST_MINI_INSTALLER_TEST_MINI_INSTALLER_TEST_CONSTANTS_H__
diff --git a/chrome/test/mini_installer_test/test.cc b/chrome/test/mini_installer_test/test.cc
new file mode 100644
index 0000000..cc61c86
--- /dev/null
+++ b/chrome/test/mini_installer_test/test.cc
@@ -0,0 +1,58 @@
+// 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.
+
+#include "chrome_mini_installer.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace {
+class MiniInstallTest : public testing::Test {
+ protected:
+ virtual void SetUp() {
+ // Currently no setup required
+ }
+
+ virtual void TearDown() {
+ // Currently no tear down required
+ }
+ };
+};
+
+// This test is disabled. See bug 1199175.
+TEST_F(MiniInstallTest, DISABLED_MiniInstallerCleanInstallTest) {
+ ChromeMiniInstaller installer;
+ installer.InstallMiniInstaller();
+ installer.UnInstall();
+}
+
+// This test is disabled. See bug 1199175.
+TEST_F(MiniInstallTest, DISABLED_MiniInstallerOverChromeSetupDevTest) {
+ ChromeMiniInstaller installer;
+ installer.OverInstall();
+ installer.UnInstall();
+}
diff --git a/chrome/test/page_cycler/SConscript b/chrome/test/page_cycler/SConscript
new file mode 100644
index 0000000..eb24fd4
--- /dev/null
+++ b/chrome/test/page_cycler/SConscript
@@ -0,0 +1,127 @@
+# 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.
+
+Import('env_test')
+
+env_test = env_test.Clone()
+
+
+env_test.Prepend(
+ CPPDEFINES = [
+ 'UI_TEST',
+ 'UNIT_TEST',
+ 'CERT_CHAIN_PARA_HAS_EXTRA_FIELDS',
+ 'WIN32_LEAN_AND_MEAN',
+ ],
+ CPPPATH = [
+ '$GTEST_DIR/include',
+ '$GTEST_DIR',
+ '$SKIA_DIR/include',
+ '$SKIA_DIR/include/corecg',
+ '$SKIA_DIR/platform',
+ '#/..',
+ ],
+ LINKFLAGS = [
+ '/INCREMENTAL',
+ '/DEBUG',
+
+ '/DELAYLOAD:"dwmapi.dll"',
+ '/DELAYLOAD:"uxtheme.dll"',
+
+ '/MACHINE:X86',
+ '/FIXED:No',
+
+ '/safeseh',
+ '/dynamicbase',
+ '/ignore:4199',
+ '/nxcompat',
+ ],
+ LIBS = [
+ 'winmm.lib',
+ 'psapi.lib',
+ 'rpcrt4.lib',
+ 'oleacc.lib',
+ 'comsupp.lib',
+
+ 'wininet.lib',
+ 'version.lib',
+ 'msimg32.lib',
+ 'ws2_32.lib',
+ 'usp10.lib',
+ 'psapi.lib',
+ 'kernel32.lib',
+ 'user32.lib',
+ 'gdi32.lib',
+ 'winspool.lib',
+ 'comdlg32.lib',
+ 'advapi32.lib',
+ 'shell32.lib',
+ 'ole32.lib',
+ 'oleaut32.lib',
+ 'uuid.lib',
+ 'odbc32.lib',
+ 'odbccp32.lib',
+
+ 'DelayImp.lib',
+ ],
+)
+
+
+input_files = [
+ '$CHROME_DIR/test/perf/mem_usage$OBJSUFFIX',
+ '$CHROME_DIR/test/ui/run_all_unittests$OBJSUFFIX',
+ '$CHROME_DIR/test/ui/ui_test$OBJSUFFIX',
+ '$CHROME_DIR/test/ui/ui_test_suite$OBJSUFFIX',
+ '$CHROME_DIR/test/test_file_util$OBJSUFFIX',
+ 'page_cycler_test.cc',
+]
+
+libs = [
+ '$GOOGLEURL_DIR/googleurl.lib',
+ '$SKIA_DIR/skia.lib',
+ '$LIBPNG_DIR/libpng.lib',
+ '$TESTING_DIR/gtest.lib',
+ '$BASE_DIR/gfx/base_gfx.lib',
+ '$ICU38_DIR/icuuc.lib',
+ '$CHROME_DIR/common/common.lib',
+ '$ZLIB_DIR/zlib.lib',
+ '$MODP_B64_DIR/modp_b64.lib',
+ '$CHROME_DIR/browser/browser.lib',
+ '$NET_DIR/net.lib',
+ '$BASE_DIR/base.lib',
+ '$CHROME_DIR/test/automation/automation.lib',
+]
+
+
+exe = env_test.Program(['page_cycler_tests',
+ 'page_cycler_tests.pdb'],
+ input_files + libs)
+i = env_test.Install('$TARGET_ROOT', exe)
+
+env_test.Alias('chrome', i)
diff --git a/chrome/test/page_cycler/page_cycler_test.cc b/chrome/test/page_cycler/page_cycler_test.cc
new file mode 100644
index 0000000..421c665
--- /dev/null
+++ b/chrome/test/page_cycler/page_cycler_test.cc
@@ -0,0 +1,328 @@
+// 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.
+
+#include "base/basictypes.h"
+#include "base/command_line.h"
+#include "base/file_util.h"
+#include "base/path_service.h"
+#include "base/process_util.h"
+#include "base/string_util.h"
+#include "chrome/browser/url_fixer_upper.h"
+#include "chrome/common/chrome_constants.h"
+#include "chrome/common/chrome_paths.h"
+#include "chrome/common/chrome_process_filter.h"
+#include "chrome/common/chrome_switches.h"
+#include "chrome/test/automation/tab_proxy.h"
+#include "chrome/test/automation/window_proxy.h"
+#include "chrome/test/ui/ui_test.h"
+#include "chrome/test/perf/mem_usage.h"
+#include "googleurl/src/gurl.h"
+#include "net/base/net_util.h"
+
+#ifndef NDEBUG
+#define TEST_ITERATIONS "2"
+#else
+#define TEST_ITERATIONS "10"
+#endif
+
+// URL at which data files may be found for HTTP tests. The document root of
+// this URL's server should point to data/page_cycler/.
+#define BASE_URL L"http://localhost:8000"
+
+namespace {
+
+class PageCyclerTest : public UITest {
+ public:
+ PageCyclerTest() {
+ show_window_ = true;
+
+ // Expose garbage collection for the page cycler tests.
+ CommandLine::AppendSwitchWithValue(&launch_arguments_,
+ switches::kJavaScriptFlags,
+ L"--expose_gc");
+ }
+
+ // For HTTP tests, the name must be safe for use in a URL without escaping.
+ void RunPageCycler(const wchar_t* name, std::wstring* pages,
+ std::wstring* timings, bool use_http) {
+ GURL test_url;
+ if (use_http) {
+ std::wstring test_path(BASE_URL);
+ file_util::AppendToPath(&test_path, name);
+ file_util::AppendToPath(&test_path, L"start.html");
+ test_url = GURL(test_path);
+ } else {
+ std::wstring test_path;
+ PathService::Get(base::DIR_EXE, &test_path);
+ file_util::UpOneDirectory(&test_path);
+ file_util::UpOneDirectory(&test_path);
+ file_util::AppendToPath(&test_path, L"data");
+ file_util::AppendToPath(&test_path, L"page_cycler");
+ file_util::AppendToPath(&test_path, name);
+ file_util::AppendToPath(&test_path, L"start.html");
+ test_url = net_util::FilePathToFileURL(test_path);
+ }
+
+ // run N iterations
+ GURL::Replacements replacements;
+ const char query_string[] = "iterations=" TEST_ITERATIONS "&auto=1";
+ replacements.SetQuery(
+ query_string,
+ url_parse::Component(0, arraysize(query_string) - 1));
+ test_url = test_url.ReplaceComponents(replacements);
+
+ scoped_ptr<TabProxy> tab(GetActiveTab());
+ tab->NavigateToURL(test_url);
+
+ // Wait for the test to finish.
+ ASSERT_TRUE(WaitUntilCookieValue(tab.get(), test_url, "__pc_done",
+ 3000, UITest::test_timeout_ms(), "1"));
+
+ std::string cookie;
+ ASSERT_TRUE(tab->GetCookieByName(test_url, "__pc_pages", &cookie));
+ pages->swap(UTF8ToWide(cookie));
+ ASSERT_FALSE(pages->empty());
+ ASSERT_TRUE(tab->GetCookieByName(test_url, "__pc_timings", &cookie));
+ timings->swap(UTF8ToWide(cookie));
+ ASSERT_FALSE(timings->empty());
+ }
+
+ void PrintIOPerfInfo(const wchar_t* test_name) {
+ printf("\n");
+ BrowserProcessFilter chrome_filter;
+ process_util::NamedProcessIterator
+ chrome_process_itr(chrome::kBrowserProcessExecutableName,
+ &chrome_filter);
+
+ const PROCESSENTRY32* chrome_entry;
+ while(chrome_entry = chrome_process_itr.NextProcessEntry()) {
+ uint32 pid = chrome_entry->th32ProcessID;
+ HANDLE process_handle = OpenProcess(PROCESS_QUERY_INFORMATION,
+ false,
+ pid);
+
+ scoped_ptr<process_util::ProcessMetrics> process_metrics;
+ IO_COUNTERS io_counters;
+ process_metrics.reset(
+ process_util::ProcessMetrics::CreateProcessMetrics(process_handle));
+ ZeroMemory(&io_counters, sizeof(io_counters));
+
+ if (process_metrics.get()->GetIOCounters(&io_counters)) {
+ wchar_t* browser_name = L"browser";
+ wchar_t* render_name = L"render";
+ wchar_t* chrome_name;
+ if (pid == chrome_filter.browser_process_id()) {
+ chrome_name = browser_name;
+ } else {
+ chrome_name = render_name;
+ }
+
+ // print out IO performance
+ wprintf(L"%s_%s_read_op = %d\n",
+ test_name, chrome_name, io_counters.ReadOperationCount);
+ wprintf(L"%s_%s_write_op = %d\n",
+ test_name, chrome_name, io_counters.WriteOperationCount);
+ wprintf(L"%s_%s_other_op = %d\n",
+ test_name, chrome_name, io_counters.OtherOperationCount);
+ wprintf(L"%s_%s_read_byte = %d K\n",
+ test_name, chrome_name, io_counters.ReadTransferCount / 1024);
+ wprintf(L"%s_%s_write_byte = %d K\n",
+ test_name, chrome_name, io_counters.WriteTransferCount / 1024);
+ wprintf(L"%s_%s_other_byte = %d K\n",
+ test_name, chrome_name, io_counters.OtherTransferCount / 1024);
+ }
+ }
+ }
+
+ void PrintMemoryUsageInfo(const wchar_t* test_name) {
+ printf("\n");
+ BrowserProcessFilter chrome_filter;
+ process_util::NamedProcessIterator
+ chrome_process_itr(chrome::kBrowserProcessExecutableName,
+ &chrome_filter);
+
+ const PROCESSENTRY32* chrome_entry;
+ while(chrome_entry = chrome_process_itr.NextProcessEntry()) {
+ uint32 pid = chrome_entry->th32ProcessID;
+ size_t peak_virtual_size;
+ size_t current_virtual_size;
+ size_t peak_working_set_size;
+ size_t current_working_set_size;
+ if (GetMemoryInfo(pid, &peak_virtual_size, &current_virtual_size,
+ &peak_working_set_size, &current_working_set_size)) {
+ if (pid == chrome_filter.browser_process_id()) {
+ wprintf(L"%s_browser_vm_peak = %d\n", test_name, peak_virtual_size);
+ wprintf(L"%s_browser_vm_final = %d\n", test_name,
+ current_virtual_size);
+ wprintf(L"%s_browser_ws_peak = %d\n", test_name,
+ peak_working_set_size);
+ wprintf(L"%s_browser_ws_final = %d\n", test_name,
+ current_working_set_size);
+ } else {
+ wprintf(L"%s_render_vm_peak = %d\n", test_name, peak_virtual_size);
+ wprintf(L"%s_render_vm_final = %d\n", test_name,
+ current_virtual_size);
+ wprintf(L"%s_render_ws_peak = %d\n", test_name,
+ peak_working_set_size);
+ wprintf(L"%s_render_ws_final = %d\n", test_name,
+ current_working_set_size);
+ }
+ }
+ };
+ }
+
+ // When use_http is true, the test name passed here will be used directly in
+ // the path to the test data, so it must be safe for use in a URL without
+ // escaping. (No pound (#), question mark (?), semicolon (;), non-ASCII, or
+ // other funny stuff.)
+ void RunTest(const wchar_t* name, bool use_http) {
+ std::wstring pages, timings;
+ RunPageCycler(name, &pages, &timings, use_http);
+ if (timings.empty())
+ return;
+
+ PrintMemoryUsageInfo(L"__pc");
+ PrintIOPerfInfo(L"__pc");
+
+ printf("\n");
+ wprintf(L"__pc_pages = [%s]\n", pages.c_str());
+ wprintf(L"__pc_timings = [%s]\n", timings.c_str());
+ }
+};
+
+class PageCyclerReferenceTest : public PageCyclerTest {
+ public:
+ // override the browser directory that is used by UITest::SetUp to cause it
+ // to use the reference build instead.
+ void SetUp() {
+ std::wstring dir;
+ PathService::Get(chrome::DIR_TEST_TOOLS, &dir);
+ file_util::AppendToPath(&dir, L"reference_build");
+ file_util::AppendToPath(&dir, L"chrome");
+ browser_directory_ = dir;
+ UITest::SetUp();
+ }
+
+ void RunTest(const wchar_t* name, bool use_http) {
+ std::wstring pages, timings;
+ RunPageCycler(name, &pages, &timings, use_http);
+ if (timings.empty())
+ return;
+
+ PrintMemoryUsageInfo(L"__pc_reference");
+ PrintIOPerfInfo(L"__pc_reference");
+
+ printf("\n");
+ wprintf(L"__pc_reference_timings = [%s]\n", timings.c_str());
+ }
+};
+
+} // namespace
+
+// file-URL tests
+TEST_F(PageCyclerTest, MozFile) {
+ RunTest(L"moz", false);
+}
+
+TEST_F(PageCyclerReferenceTest, MozFile) {
+ RunTest(L"moz", false);
+}
+
+TEST_F(PageCyclerTest, Intl1File) {
+ RunTest(L"intl1", false);
+}
+
+TEST_F(PageCyclerReferenceTest, Intl1File) {
+ RunTest(L"intl1", false);
+}
+
+TEST_F(PageCyclerTest, Intl2File) {
+ RunTest(L"intl2", false);
+}
+
+TEST_F(PageCyclerReferenceTest, Intl2File) {
+ RunTest(L"intl2", false);
+}
+
+TEST_F(PageCyclerTest, DomFile) {
+ RunTest(L"dom", false);
+}
+
+TEST_F(PageCyclerReferenceTest, DomFile) {
+ RunTest(L"dom", false);
+}
+
+TEST_F(PageCyclerTest, DhtmlFile) {
+ RunTest(L"dhtml", false);
+}
+
+TEST_F(PageCyclerReferenceTest, DhtmlFile) {
+ RunTest(L"dhtml", false);
+}
+
+// http (localhost) tests
+TEST_F(PageCyclerTest, MozHttp) {
+ RunTest(L"moz", true);
+}
+
+TEST_F(PageCyclerReferenceTest, MozHttp) {
+ RunTest(L"moz", true);
+}
+
+TEST_F(PageCyclerTest, Intl1Http) {
+ RunTest(L"intl1", true);
+}
+
+TEST_F(PageCyclerReferenceTest, Intl1Http) {
+ RunTest(L"intl1", true);
+}
+
+TEST_F(PageCyclerTest, Intl2Http) {
+ RunTest(L"intl2", true);
+}
+
+TEST_F(PageCyclerReferenceTest, Intl2Http) {
+ RunTest(L"intl2", true);
+}
+
+TEST_F(PageCyclerTest, DomHttp) {
+ RunTest(L"dom", true);
+}
+
+TEST_F(PageCyclerReferenceTest, DomHttp) {
+ RunTest(L"dom", true);
+}
+
+TEST_F(PageCyclerTest, BloatHttp) {
+ RunTest(L"bloat", true);
+}
+
+TEST_F(PageCyclerReferenceTest, BloatHttp) {
+ RunTest(L"bloat", true);
+}
diff --git a/chrome/test/page_cycler/page_cycler_tests.vcproj b/chrome/test/page_cycler/page_cycler_tests.vcproj
new file mode 100644
index 0000000..a3a7025
--- /dev/null
+++ b/chrome/test/page_cycler/page_cycler_tests.vcproj
@@ -0,0 +1,210 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="page_cycler_tests"
+ ProjectGUID="{C9E0BD1D-B175-4A91-8380-3FDC81FAB9D7}"
+ RootNamespace="page_cycler_tests"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ ConfigurationType="1"
+ InheritedPropertySheets="$(SolutionDir)..\build\common.vsprops;$(SolutionDir)..\build\debug.vsprops;..\..\tools\build\win\precompiled_wtl.vsprops;..\..\tools\build\win\unit_test.vsprops;..\..\tools\build\win\ui_test.vsprops;..\..\tools\build\win\test_memory_usage.vsprops;$(SolutionDir)..\skia\using_skia.vsprops;$(SolutionDir)..\testing\using_gtest.vsprops"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="winmm.lib"
+ />
+ <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"
+ ConfigurationType="1"
+ InheritedPropertySheets="$(SolutionDir)..\build\common.vsprops;$(SolutionDir)..\build\release.vsprops;..\..\tools\build\win\unit_test.vsprops;..\..\tools\build\win\ui_test.vsprops;..\..\tools\build\win\test_memory_usage.vsprops;$(SolutionDir)..\skia\using_skia.vsprops;$(SolutionDir)..\testing\using_gtest.vsprops"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="winmm.lib"
+ />
+ <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="Common"
+ >
+ <File
+ RelativePath="..\..\tools\build\win\precompiled_wtl.cc"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="1"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\tools\build\win\precompiled_wtl.h"
+ >
+ </File>
+ <File
+ RelativePath="..\ui\run_all_unittests.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\test_file_util.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\testing_browser_process.h"
+ >
+ </File>
+ <File
+ RelativePath="..\ui\ui_test.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\ui\ui_test.h"
+ >
+ </File>
+ <File
+ RelativePath="..\ui\ui_test_suite.cc"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="MemoryUsage"
+ >
+ <File
+ RelativePath="..\perf\mem_usage.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\perf\mem_usage.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="TestPageCycler"
+ >
+ <File
+ RelativePath=".\page_cycler_test.cc"
+ >
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/chrome/test/perf/mem_usage.cc b/chrome/test/perf/mem_usage.cc
new file mode 100644
index 0000000..c8ec78c
--- /dev/null
+++ b/chrome/test/perf/mem_usage.cc
@@ -0,0 +1,98 @@
+// 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.
+
+#include <windows.h>
+#include <psapi.h>
+
+#include "base/basictypes.h"
+#include "base/process_util.h"
+#include "chrome/common/chrome_constants.h"
+#include "chrome/common/chrome_process_filter.h"
+#include "chrome/test/perf/mem_usage.h"
+
+bool GetMemoryInfo(uint32 process_id,
+ size_t *peak_virtual_size,
+ size_t *current_virtual_size,
+ size_t *peak_working_set_size,
+ size_t *current_working_set_size) {
+
+ if (!peak_virtual_size || !current_virtual_size)
+ return false;
+
+ HANDLE process_handle = OpenProcess(PROCESS_QUERY_INFORMATION |
+ PROCESS_VM_READ,
+ FALSE, process_id);
+ if (!process_handle)
+ return false;
+
+ PROCESS_MEMORY_COUNTERS_EX pmc;
+ bool result = false;
+ if (GetProcessMemoryInfo(process_handle,
+ reinterpret_cast<PPROCESS_MEMORY_COUNTERS>(&pmc),
+ sizeof(pmc))) {
+ *peak_virtual_size = pmc.PeakPagefileUsage;
+ *current_virtual_size = pmc.PagefileUsage;
+ *peak_working_set_size = pmc.PeakWorkingSetSize;
+ *current_working_set_size = pmc.WorkingSetSize;
+ result = true;
+ }
+
+ CloseHandle(process_handle);
+ return result;
+}
+
+void PrintChromeMemoryUsageInfo() {
+ printf("\n");
+ BrowserProcessFilter chrome_filter;
+ process_util::NamedProcessIterator
+ chrome_process_itr(chrome::kBrowserProcessExecutableName, &chrome_filter);
+
+ const PROCESSENTRY32* chrome_entry;
+ while(chrome_entry = chrome_process_itr.NextProcessEntry()) {
+ uint32 pid = chrome_entry->th32ProcessID;
+ size_t peak_virtual_size;
+ size_t current_virtual_size;
+ size_t peak_working_set_size;
+ size_t current_working_set_size;
+ if (GetMemoryInfo(pid, &peak_virtual_size, &current_virtual_size,
+ &peak_working_set_size, &current_working_set_size)) {
+ if (pid == chrome_filter.browser_process_id()) {
+ wprintf(L"browser_vm_peak = %d\n", peak_virtual_size);
+ wprintf(L"browser_vm_current = %d\n", current_virtual_size);
+ wprintf(L"browser_ws_peak = %d\n", peak_working_set_size);
+ wprintf(L"browser_ws_final = %d\n", current_working_set_size);
+ } else {
+ wprintf(L"render_vm_peak = %d\n", peak_virtual_size);
+ wprintf(L"render_vm_current = %d\n", current_virtual_size);
+ wprintf(L"render_ws_peak = %d\n", peak_working_set_size);
+ wprintf(L"render_ws_final = %d\n", current_working_set_size);
+ }
+ }
+ };
+}
diff --git a/chrome/test/perf/mem_usage.h b/chrome/test/perf/mem_usage.h
new file mode 100644
index 0000000..940a0d1
--- /dev/null
+++ b/chrome/test/perf/mem_usage.h
@@ -0,0 +1,64 @@
+// 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.
+
+#ifndef CHROME_TEST_PERF_MEM_USAGE_H__
+#define CHROME_TEST_PERF_MEM_USAGE_H__
+
+// Get memory information for the process with given process ID.
+//
+// The Windows psapi provides memory information of a process through structure
+// RPROCESS_MEMORY_COUNTERS_EX. Relevant fields are:
+// PagefileUsage: private (not shared) committed virtual space in process.
+// This is "VM Size" in task manager processes tab.
+// PeakPagefileUsage: peak value of PagefileUsage.
+// WorkingSetSize: physical memory allocated to process including shared pages.
+// This is "Memory Usage" in task manager processes tab.
+// Contrary to its name, this value is not much useful for
+// tracking the memory demand of an application.
+// PeakWorkingSetSize: peak value of WorkingSetSize.
+// This is "Peak Memory Usage" in task manager processes
+// tab.
+// PrivateUsage: The current amount of memory that cannot be shared with other
+// processes. Private bytes include memory that is committed and
+// marked MEM_PRIVATE, data that is not mapped, and executable
+// pages that have been written to. It usually gives the same
+// value as PagefileUsage. No equivalent part in task manager.
+//
+// The measurements we use are PagefileUsage (returned by current_virtual_size)
+// and PeakPagefileUsage (returned by peak_virtual_size), Working Set and
+// Peak working Set.
+bool GetMemoryInfo(uint32 process_id,
+ size_t *peak_virtual_size,
+ size_t *current_virtual_size,
+ size_t *peak_working_set_size,
+ size_t *current_working_set_size);
+
+// Get and print memory usage information for running chrome processes.
+void PrintChromeMemoryUsageInfo();
+#endif // CHROME_TEST_PERF_MEM_USAGE_H__
diff --git a/chrome/test/perf/perftests.cc b/chrome/test/perf/perftests.cc
new file mode 100644
index 0000000..c76bc69
--- /dev/null
+++ b/chrome/test/perf/perftests.cc
@@ -0,0 +1,77 @@
+// 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.
+
+#include "base/message_loop.h"
+#include "base/perftimer.h"
+#include "chrome/common/chrome_paths.cc"
+#include "testing/gtest/include/gtest/gtest.h"
+
+// TODO(darin): share code with base/run_all_perftests.cc
+
+int main(int argc, char **argv) {
+ chrome::RegisterPathProvider();
+ MessageLoop main_message_loop;
+
+ testing::InitGoogleTest(&argc, argv);
+
+ const char log_file_switch[] = "-o";
+ const char* log_filename = NULL;
+ for (int i = 1; i < argc; i++) {
+ if (strcmp(argv[i], log_file_switch) == 0) {
+ // found the switch for the log file, use the next arg
+ if (i >= argc - 1) {
+ fprintf(stderr, "Log file not specified");
+ return 1;
+ }
+ log_filename = argv[i + 1];
+ }
+ }
+ if (!log_filename) {
+ // use the default filename
+ log_filename = "perf_test.log";
+ }
+ printf("Using output file \"%s\" (change with %s <filename>)\n",
+ log_filename, log_file_switch);
+
+ if (!InitPerfLog(log_filename)) {
+ fprintf(stderr, "Unable to open log file\n");
+ return 1;
+ }
+
+ // Raise to high priority to have more precise measurements. Since we don't
+ // aim at 1% precision, it is not necessary to run at realtime level.
+ if (!IsDebuggerPresent()) {
+ SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS);
+ }
+
+ int result = RUN_ALL_TESTS();
+
+ FinalizePerfLog();
+ return result;
+}
diff --git a/chrome/test/perf/perftests.vcproj b/chrome/test/perf/perftests.vcproj
new file mode 100644
index 0000000..44435d5
--- /dev/null
+++ b/chrome/test/perf/perftests.vcproj
@@ -0,0 +1,207 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="perf_tests"
+ ProjectGUID="{9055E088-25C6-47FD-87D5-D9DD9FD75C9F}"
+ RootNamespace="perf_tests"
+ Keyword="Win32Proj"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ ConfigurationType="1"
+ InheritedPropertySheets="$(SolutionDir)..\build\common.vsprops;$(SolutionDir)..\build\debug.vsprops;$(SolutionDir)..\third_party\icu38\build\using_icu.vsprops;$(SolutionDir)..\third_party\libxml\build\using_libxml.vsprops;$(SolutionDir)..\testing\using_gtest.vsprops"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ PreprocessorDefinitions="PERF_TEST;_CRT_RAND_S"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="shlwapi.lib rpcrt4.lib winmm.lib"
+ SubSystem="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"
+ ConfigurationType="1"
+ InheritedPropertySheets="$(SolutionDir)..\build\common.vsprops;$(SolutionDir)..\build\release.vsprops;$(SolutionDir)..\third_party\icu38\build\using_icu.vsprops;$(SolutionDir)..\third_party\libxml\build\using_libxml.vsprops;$(SolutionDir)..\testing\using_gtest.vsprops"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ PreprocessorDefinitions="PERF_TEST;_CRT_RAND_S"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="shlwapi.lib rpcrt4.lib winmm.lib"
+ SubSystem="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="TestVisitedLink"
+ >
+ <File
+ RelativePath="..\..\browser\visitedlink_master.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\browser\visitedlink_perftest.cc"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Common"
+ >
+ <File
+ RelativePath=".\perftests.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\base\perftimer.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\test_file_util.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\test_file_util.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="TestURLParser"
+ >
+ <File
+ RelativePath=".\url_parse_perftest.cc"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="TestJSONSerializer"
+ >
+ <File
+ RelativePath="..\..\common\json_value_serializer_perftest.cc"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="TestSafeBrowsing"
+ >
+ <File
+ RelativePath="..\..\browser\safe_browsing\database_perftest.cc"
+ >
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/chrome/test/perf/url_parse_perftest.cc b/chrome/test/perf/url_parse_perftest.cc
new file mode 100644
index 0000000..2dc6153
--- /dev/null
+++ b/chrome/test/perf/url_parse_perftest.cc
@@ -0,0 +1,175 @@
+// 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.
+
+#include "base/perftimer.h"
+#include "googleurl/src/gurl.h"
+#include "googleurl/src/url_canon.h"
+#include "googleurl/src/url_canon_stdstring.h"
+#include "googleurl/src/url_parse.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+// TODO(darin): chrome code should not depend on WebCore innards
+#if 0
+#pragma warning(push, 0)
+
+// This is because we have multiple headers called "CString.h" and KURL.cpp
+// can grab the wrong one.
+#include "webkit/third_party/WebCore/platform/CString.h"
+
+#undef USE_GOOGLE_URL_LIBRARY
+#define KURL WebKitKURL
+#include "KURL.h"
+#include "KURL.cpp"
+#pragma warning(pop)
+
+TEST(URLParse, FullURL) {
+ const char url[] = "http://me:pass@host/foo/bar.html;param?query=yes#ref";
+ int url_len = static_cast<int>(strlen(url));
+
+ url_parse::Parsed parsed;
+ PerfTimeLogger timer("Full_URL_Parse_AMillion");
+
+ for (int i = 0; i < 1000000; i++)
+ url_parse::ParseStandardURL(url, url_len, &parsed);
+ timer.Done();
+}
+
+namespace {
+
+const char typical_url1[] = "http://www.google.com/search?q=url+parsing&ie=utf-8&oe=utf-8&aq=t&rls=org.mozilla:en-US:official&client=firefox-a";
+int typical_url1_len = static_cast<int>(strlen(typical_url1));
+
+const char typical_url2[] = "http://www.amazon.com/Stephen-King-Thrillers-Horror-People/dp/0766012336/ref=sr_1_2/133-4144931-4505264?ie=UTF8&s=books&qid=2144880915&sr=8-2";
+int typical_url2_len = static_cast<int>(strlen(typical_url2));
+
+const char typical_url3[] = "http://store.apple.com/1-800-MY-APPLE/WebObjects/AppleStore.woa/wa/RSLID?nnmm=browse&mco=578E9744&node=home/desktop/mac_pro";
+int typical_url3_len = static_cast<int>(strlen(typical_url3));
+
+}
+
+TEST(URLParse, TypicalURLParse) {
+ url_parse::Parsed parsed1;
+ url_parse::Parsed parsed2;
+ url_parse::Parsed parsed3;
+
+ // Do this 1/3 of a million times since we do 3 different URLs.
+ PerfTimeLogger parse_timer("Typical_URL_Parse_AMillion");
+ for (int i = 0; i < 333333; i++) {
+ url_parse::ParseStandardURL(typical_url1, typical_url1_len, &parsed1);
+ url_parse::ParseStandardURL(typical_url2, typical_url2_len, &parsed2);
+ url_parse::ParseStandardURL(typical_url3, typical_url3_len, &parsed3);
+ }
+ parse_timer.Done();
+}
+
+// Includes both parsing and canonicalization with no mallocs.
+TEST(URLParse, TypicalURLParseCanon) {
+ url_parse::Parsed parsed1;
+ url_parse::Parsed parsed2;
+ url_parse::Parsed parsed3;
+
+ PerfTimeLogger canon_timer("Typical_Parse_Canon_AMillion");
+ url_parse::Parsed out_parsed;
+ url_canon::RawCanonOutput<1024> output;
+ for (int i = 0; i < 333333; i++) { // divide by 3 so we get 1M
+ url_parse::ParseStandardURL(typical_url1, typical_url1_len, &parsed1);
+ output.set_length(0);
+ url_canon::CanonicalizeStandardURL(typical_url1, typical_url1_len, parsed1,
+ NULL, &output, &out_parsed);
+
+ url_parse::ParseStandardURL(typical_url2, typical_url2_len, &parsed2);
+ output.set_length(0);
+ url_canon::CanonicalizeStandardURL(typical_url2, typical_url2_len, parsed2,
+ NULL, &output, &out_parsed);
+
+ url_parse::ParseStandardURL(typical_url3, typical_url3_len, &parsed3);
+ output.set_length(0);
+ url_canon::CanonicalizeStandardURL(typical_url3, typical_url3_len, parsed3,
+ NULL, &output, &out_parsed);
+ }
+ canon_timer.Done();
+}
+
+// Includes both parsing and canonicalization, and mallocs for the output.
+TEST(URLParse, TypicalURLParseCanonStdString) {
+ url_parse::Parsed parsed1;
+ url_parse::Parsed parsed2;
+ url_parse::Parsed parsed3;
+
+ PerfTimeLogger canon_timer("Typical_Parse_Canon_AMillion");
+ url_parse::Parsed out_parsed;
+ for (int i = 0; i < 333333; i++) { // divide by 3 so we get 1M
+ url_parse::ParseStandardURL(typical_url1, typical_url1_len, &parsed1);
+ std::string out1;
+ url_canon::StdStringCanonOutput output1(&out1);
+ url_canon::CanonicalizeStandardURL(typical_url1, typical_url1_len, parsed1,
+ NULL, &output1, &out_parsed);
+
+ url_parse::ParseStandardURL(typical_url2, typical_url2_len, &parsed2);
+ std::string out2;
+ url_canon::StdStringCanonOutput output2(&out2);
+ url_canon::CanonicalizeStandardURL(typical_url2, typical_url2_len, parsed2,
+ NULL, &output2, &out_parsed);
+
+ url_parse::ParseStandardURL(typical_url3, typical_url3_len, &parsed3);
+ std::string out3;
+ url_canon::StdStringCanonOutput output3(&out3);
+ url_canon::CanonicalizeStandardURL(typical_url3, typical_url3_len, parsed3,
+ NULL, &output3, &out_parsed);
+ }
+ canon_timer.Done();
+}
+
+TEST(URLParse, GURL) {
+ // Don't want to time creating the input strings.
+ std::string stdurl1(typical_url1);
+ std::string stdurl2(typical_url2);
+ std::string stdurl3(typical_url3);
+
+ PerfTimeLogger gurl_timer("Typical_GURL_AMillion");
+ for (int i = 0; i < 333333; i++) { // divide by 3 so we get 1M
+ GURL gurl1(stdurl1);
+ GURL gurl2(stdurl2);
+ GURL gurl3(stdurl3);
+ }
+ gurl_timer.Done();
+}
+
+// TODO(darin): chrome code should not depend on WebCore innards
+TEST(URLParse, KURL) {
+ PerfTimeLogger timer_kurl("Typical_KURL_AMillion");
+ for (int i = 0; i < 333333; i++) { // divide by 3 so we get 1M
+ WebCore::WebKitKURL kurl1(typical_url1);
+ WebCore::WebKitKURL kurl2(typical_url2);
+ WebCore::WebKitKURL kurl3(typical_url3);
+ }
+ timer_kurl.Done();
+}
+
+#endif \ No newline at end of file
diff --git a/chrome/test/plugin/SConscript b/chrome/test/plugin/SConscript
new file mode 100644
index 0000000..6ad1cdc
--- /dev/null
+++ b/chrome/test/plugin/SConscript
@@ -0,0 +1,130 @@
+# 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.
+
+Import('env_test')
+
+env_test = env_test.Clone()
+
+
+env_test.Prepend(
+ CPPDEFINES = [
+ 'UI_TEST',
+ 'UNIT_TEST',
+ 'LIBXSLT_STATIC',
+ 'LIBXML_STATIC',
+ 'CERT_CHAIN_PARA_HAS_EXTRA_FIELDS',
+ 'WIN32_LEAN_AND_MEAN',
+ ],
+ CPPPATH = [
+ '$GTEST_DIR/include',
+ '$GTEST_DIR',
+ '$SKIA_DIR/include',
+ '$SKIA_DIR/include/corecg',
+ '$SKIA_DIR/platform',
+ '#/..',
+ '$LIBXSLT_DIR',
+ '$LIBXML_DIR/includ',
+ ],
+ LINKFLAGS = [
+ '/INCREMENTAL',
+ '/DEBUG',
+
+ '/DELAYLOAD:"ws2_32.dll"',
+ '/DELAYLOAD:"dwmapi.dll"',
+ '/DELAYLOAD:"uxtheme.dll"',
+
+ '/MACHINE:X86',
+ '/FIXED:No',
+
+ '/safeseh',
+ '/dynamicbase',
+ '/ignore:4199',
+ '/nxcompat',
+ ],
+ LIBS = [
+ 'winmm.lib',
+ 'rpcrt4.lib',
+ 'oleacc.lib',
+ 'comsupp.lib',
+
+ 'wininet.lib',
+ 'version.lib',
+ 'msimg32.lib',
+ 'ws2_32.lib',
+ 'usp10.lib',
+ 'psapi.lib',
+ 'kernel32.lib',
+ 'user32.lib',
+ 'gdi32.lib',
+ 'winspool.lib',
+ 'comdlg32.lib',
+ 'advapi32.lib',
+ 'shell32.lib',
+ 'ole32.lib',
+ 'oleaut32.lib',
+ 'uuid.lib',
+ 'odbc32.lib',
+ 'odbccp32.lib',
+
+ 'DelayImp.lib',
+ ],
+)
+
+input_files = [
+ '$CHROME_DIR/test/ui/run_all_unittests$OBJSUFFIX',
+ '$CHROME_DIR/test/ui/ui_test$OBJSUFFIX',
+ '$CHROME_DIR/test/ui/ui_test_suite$OBJSUFFIX',
+ '$CHROME_DIR/test/test_file_util$OBJSUFFIX',
+ 'plugin_test.cpp',
+]
+
+libs = [
+ '$GOOGLEURL_DIR/googleurl.lib',
+ '$CHROME_DIR/test/security_tests/security_tests.lib',
+ '$SKIA_DIR/skia.lib',
+ '$LIBPNG_DIR/libpng.lib',
+ '$TESTING_DIR/gtest.lib',
+ '$BASE_DIR/gfx/base_gfx.lib',
+ '$ICU38_DIR/icuuc.lib',
+ '$CHROME_DIR/common/common.lib',
+ '$ZLIB_DIR/zlib.lib',
+ '$MODP_B64_DIR/modp_b64.lib',
+ '$CHROME_DIR/browser/browser.lib',
+ '$NET_DIR/net.lib',
+ '$BASE_DIR/base.lib',
+ '$CHROME_DIR/test/automation/automation.lib',
+]
+
+
+exe = env_test.Program(['plugin_tests',
+ 'plugin_tests.pdb'],
+ input_files + libs)
+i = env_test.Install('$TARGET_ROOT', exe)
+
+env_test.Alias('chrome', i)
diff --git a/chrome/test/plugin/plugin_test.cpp b/chrome/test/plugin/plugin_test.cpp
new file mode 100644
index 0000000..c9f16c1
--- /dev/null
+++ b/chrome/test/plugin/plugin_test.cpp
@@ -0,0 +1,232 @@
+// 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.
+
+// Tests for the top plugins to catch regressions in our plugin host code, as
+// well as in the out of process code. Currently this tests:
+// Flash
+// Real
+// QuickTime
+// Windows Media Player
+// -this includes both WMP plugins. npdsplay.dll is the older one that
+// comes with XP. np-mswmp.dll can be downloaded from Microsoft and
+// needs SP2 or Vista.
+
+#include <windows.h>
+#include <shellapi.h>
+#include <shlobj.h>
+#include <atlbase.h>
+#include <comutil.h>
+
+#include <stdlib.h>
+#include <string.h>
+#include <memory.h>
+
+#include "base/file_util.h"
+#include "base/registry.h"
+#include "chrome/common/chrome_switches.h"
+#include "chrome/common/chrome_paths.h"
+#include "chrome/test/automation/tab_proxy.h"
+#include "chrome/test/ui/ui_test.h"
+#include "net/base/net_util.h"
+#include "webkit/glue/plugins/plugin_list.h"
+
+const char kTestCompleteCookie[] = "status";
+const char kTestCompleteSuccess[] = "OK";
+const int kShortWaitTimeout = 10 * 1000;
+const int kLongWaitTimeout = 30 * 1000;
+
+class PluginTest : public UITest {
+ protected:
+ virtual void SetUp() {
+ const testing::TestInfo* const test_info =
+ testing::UnitTest::GetInstance()->current_test_info();
+ if (strcmp(test_info->name(), "MediaPlayerNew") == 0) {
+ // The installer adds our process names to the registry key below. Since
+ // the installer might not have run on this machine, add it manually.
+ RegKey regkey;
+ if (regkey.Open(HKEY_LOCAL_MACHINE,
+ L"Software\\Microsoft\\MediaPlayer\\ShimInclusionList",
+ KEY_WRITE)) {
+ regkey.CreateKey(L"CHROME.EXE", KEY_READ);
+ }
+ if (!launch_arguments_.empty())
+ launch_arguments_.append(L" ");
+ launch_arguments_.append(L"--" kNoNativeActiveXShimSwitch);
+
+ } else if (strcmp(test_info->name(), "MediaPlayerOld") == 0) {
+ // When testing the old WMP plugin, we need to force Chrome to not load
+ // the new plugin.
+ if (!launch_arguments_.empty())
+ launch_arguments_.append(L" ");
+
+ launch_arguments_.append(L"--" kUseOldWMPPluginSwitch);
+ launch_arguments_.append(L" ");
+ launch_arguments_.append(L"--" kNoNativeActiveXShimSwitch);
+ } else if (strcmp(test_info->name(), "FlashSecurity") == 0) {
+ if (!launch_arguments_.empty())
+ launch_arguments_.append(L" ");
+
+ launch_arguments_.append(L"--");
+ launch_arguments_.append(switches::kTestSandbox);
+ launch_arguments_.append(L"=");
+ launch_arguments_.append(L"security_tests.dll");
+ }
+
+ UITest::SetUp();
+ }
+
+ void TestPlugin(const std::wstring& test_case, int timeout) {
+ GURL url = GetTestUrl(test_case);
+ NavigateToURL(url);
+ WaitForFinish(timeout);
+ }
+
+ // Generate the URL for testing a particular test.
+ // HTML for the tests is all located in test_directory\plugin\<testcase>
+ GURL GetTestUrl(const std::wstring &test_case) {
+ std::wstring path;
+ PathService::Get(chrome::DIR_TEST_DATA, &path);
+ file_util::AppendToPath(&path, L"plugin");
+ file_util::AppendToPath(&path, test_case);
+ return net_util::FilePathToFileURL(path);
+ }
+
+ // Waits for the test case to finish.
+ void WaitForFinish(const int wait_time) {
+ const int kSleepTime = 500; // 2 times per second
+ const int kMaxIntervals = wait_time / kSleepTime;
+
+ GURL url = GetTestUrl(L"done");
+ scoped_ptr<TabProxy> tab(GetActiveTab());
+
+ std::string done_str;
+ for (int i = 0; i < kMaxIntervals; ++i) {
+ Sleep(kSleepTime);
+
+ // The webpage being tested has javascript which sets a cookie
+ // which signals completion of the test.
+ std::string cookieName = kTestCompleteCookie;
+ tab->GetCookieByName(url, cookieName, &done_str);
+ if (!done_str.empty())
+ break;
+ }
+
+ EXPECT_EQ(kTestCompleteSuccess, done_str);
+ }
+};
+
+TEST_F(PluginTest, Quicktime) {
+ TestPlugin(L"quicktime.html", kShortWaitTimeout);
+}
+
+TEST_F(PluginTest, MediaPlayerNew) {
+ TestPlugin(L"wmp_new.html", kShortWaitTimeout);
+}
+
+TEST_F(PluginTest, MediaPlayerOld) {
+ TestPlugin(L"wmp_old.html", kLongWaitTimeout);
+}
+
+TEST_F(PluginTest, Real) {
+ TestPlugin(L"real.html", kShortWaitTimeout);
+}
+
+TEST_F(PluginTest, Flash) {
+ TestPlugin(L"flash.html", kShortWaitTimeout);
+}
+
+TEST_F(PluginTest, FlashOctetStream) {
+ TestPlugin(L"flash-octet-stream.html", kShortWaitTimeout);
+}
+
+TEST_F(PluginTest, FlashSecurity) {
+ TestPlugin(L"flash.html", kShortWaitTimeout);
+}
+
+TEST_F(PluginTest, Java) {
+ TestPlugin(L"Java.html", kShortWaitTimeout);
+}
+
+TEST_F(PluginTest, Silverlight) {
+ TestPlugin(L"silverlight.html", kShortWaitTimeout);
+}
+
+typedef HRESULT (__stdcall* DllRegUnregServerFunc)();
+
+class ActiveXTest : public PluginTest {
+ public:
+ ActiveXTest() {
+ dll_registered = false;
+ }
+ protected:
+ void TestActiveX(const std::wstring& test_case, int timeout, bool reg_dll) {
+ if (reg_dll) {
+ RegisterTestControl(true);
+ dll_registered = true;
+ }
+ TestPlugin(test_case, timeout);
+ }
+ virtual void TearDown() {
+ PluginTest::TearDown();
+ if (dll_registered)
+ RegisterTestControl(false);
+ }
+ void RegisterTestControl(bool register_server) {
+ std::wstring test_control_path = browser_directory_ +
+ L"\\activex_test_control.dll";
+ HMODULE h = LoadLibrary(test_control_path.c_str());
+ ASSERT_TRUE(h != NULL) << "Failed to load activex_test_control.dll";
+ const char* func_name = register_server ?
+ "DllRegisterServer" : "DllUnregisterServer";
+ DllRegUnregServerFunc func = reinterpret_cast<DllRegUnregServerFunc>(
+ GetProcAddress(h, func_name));
+ // This should never happen actually.
+ ASSERT_TRUE(func != NULL) << "Failed to find reg/unreg function.";
+ HRESULT hr = func();
+ const char* error_message = register_server ? "Failed to register dll."
+ : "Failed to unregister dll";
+ ASSERT_TRUE(SUCCEEDED(hr)) << error_message;
+ FreeLibrary(h);
+ }
+ private:
+ bool dll_registered;
+};
+
+TEST_F(ActiveXTest, EmbeddedWMP) {
+ TestActiveX(L"activex_embedded_wmp.html", kLongWaitTimeout, false);
+}
+
+TEST_F(ActiveXTest, WMP) {
+ TestActiveX(L"activex_wmp.html", kLongWaitTimeout, false);
+}
+
+TEST_F(ActiveXTest, CustomScripting) {
+ TestActiveX(L"activex_custom_scripting.html", kShortWaitTimeout, true);
+}
+
diff --git a/chrome/test/plugin/plugin_tests.vcproj b/chrome/test/plugin/plugin_tests.vcproj
new file mode 100644
index 0000000..f8fca50
--- /dev/null
+++ b/chrome/test/plugin/plugin_tests.vcproj
@@ -0,0 +1,190 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="plugin_tests"
+ ProjectGUID="{A1CAA831-C507-4B2E-87F3-AEC63C9907F9}"
+ RootNamespace="plugin_tests"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ ConfigurationType="1"
+ InheritedPropertySheets="$(SolutionDir)..\build\common.vsprops;$(SolutionDir)..\build\debug.vsprops;..\..\tools\build\win\precompiled_wtl.vsprops;$(SolutionDir)..\third_party\libxml\build\using_libxml.vsprops;$(SolutionDir)..\third_party\libxslt\build\using_libxslt.vsprops;..\..\tools\build\win\unit_test.vsprops;..\..\tools\build\win\ui_test.vsprops;$(SolutionDir)..\skia\using_skia.vsprops;$(SolutionDir)..\testing\using_gtest.vsprops"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="winmm.lib"
+ />
+ <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"
+ ConfigurationType="1"
+ InheritedPropertySheets="$(SolutionDir)..\build\common.vsprops;$(SolutionDir)..\build\release.vsprops;$(SolutionDir)..\third_party\libxml\build\using_libxml.vsprops;$(SolutionDir)..\third_party\libxslt\build\using_libxslt.vsprops;..\..\tools\build\win\unit_test.vsprops;..\..\tools\build\win\ui_test.vsprops;$(SolutionDir)..\skia\using_skia.vsprops;$(SolutionDir)..\testing\using_gtest.vsprops"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="winmm.lib"
+ />
+ <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>
+ <File
+ RelativePath=".\plugin_test.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\tools\build\win\precompiled_wtl.cc"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="1"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\tools\build\win\precompiled_wtl.h"
+ >
+ </File>
+ <File
+ RelativePath="..\ui\run_all_unittests.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\test_file_util.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\testing_browser_process.h"
+ >
+ </File>
+ <File
+ RelativePath="..\ui\ui_test.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\ui\ui_test.h"
+ >
+ </File>
+ <File
+ RelativePath="..\ui\ui_test_suite.cc"
+ >
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/chrome/test/reliability/SConscript b/chrome/test/reliability/SConscript
new file mode 100644
index 0000000..e0b0a32
--- /dev/null
+++ b/chrome/test/reliability/SConscript
@@ -0,0 +1,125 @@
+# 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.
+
+Import('env_test')
+
+env_test = env_test.Clone()
+
+
+env_test.Prepend(
+ CPPDEFINES = [
+ 'RELIABILITY_TEST', # seems to be unused
+ 'UI_TEST',
+ 'UNIT_TEST',
+ 'CERT_CHAIN_PARA_HAS_EXTRA_FIELDS',
+ 'WIN32_LEAN_AND_MEAN',
+ ],
+ CPPPATH = [
+ '$GTEST_DIR/include',
+ '$GTEST_DIR',
+ '$SKIA_DIR/include',
+ '$SKIA_DIR/include/corecg',
+ '$SKIA_DIR/platform',
+ '#/..',
+ ],
+ LINKFLAGS = [
+ '/INCREMENTAL',
+ '/DEBUG',
+
+ '/DELAYLOAD:"dwmapi.dll"',
+ '/DELAYLOAD:"uxtheme.dll"',
+
+ '/MACHINE:X86',
+ '/FIXED:No',
+
+ '/safeseh',
+ '/dynamicbase',
+ '/ignore:4199',
+ '/nxcompat',
+ ],
+ LIBS = [
+ 'winmm.lib',
+ 'psapi.lib',
+ 'rpcrt4.lib',
+ 'oleacc.lib',
+ 'comsupp.lib',
+
+ 'wininet.lib',
+ 'version.lib',
+ 'msimg32.lib',
+ 'ws2_32.lib',
+ 'usp10.lib',
+ 'psapi.lib',
+ 'kernel32.lib',
+ 'user32.lib',
+ 'gdi32.lib',
+ 'winspool.lib',
+ 'comdlg32.lib',
+ 'advapi32.lib',
+ 'shell32.lib',
+ 'ole32.lib',
+ 'oleaut32.lib',
+ 'uuid.lib',
+ 'odbc32.lib',
+ 'odbccp32.lib',
+
+ 'DelayImp.lib',
+ ],
+)
+
+input_files = [
+ '$CHROME_DIR/test/perf/mem_usage$OBJSUFFIX',
+ '$CHROME_DIR/test/ui/ui_test$OBJSUFFIX',
+ '$CHROME_DIR/test/ui/ui_test_suite$OBJSUFFIX',
+ '$CHROME_DIR/test/test_file_util$OBJSUFFIX',
+ 'page_load_test.cc',
+ 'run_all_unittests.cc',
+]
+
+libs = [
+ '$GOOGLEURL_DIR/googleurl.lib',
+ '$SKIA_DIR/skia.lib',
+ '$LIBPNG_DIR/libpng.lib',
+ '$TESTING_DIR/gtest.lib',
+ '$BASE_DIR/gfx/base_gfx.lib',
+ '$ICU38_DIR/icuuc.lib',
+ '$CHROME_DIR/common/common.lib',
+ '$ZLIB_DIR/zlib.lib',
+ '$CHROME_DIR/browser/browser.lib',
+ '$BASE_DIR/base.lib',
+ '$CHROME_DIR/test/automation/automation.lib',
+]
+
+
+exe = env_test.Program(['reliability_tests',
+ 'reliability_tests.pdb'],
+ input_files + libs)
+i = env_test.Install('$TARGET_ROOT', exe)
+
+env_test.Alias('chrome', i)
diff --git a/chrome/test/reliability/page_load_test.cc b/chrome/test/reliability/page_load_test.cc
new file mode 100644
index 0000000..ee59ad6
--- /dev/null
+++ b/chrome/test/reliability/page_load_test.cc
@@ -0,0 +1,600 @@
+// 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.
+//
+// This file provides reliablity test which runs under UI test framework. The
+// test is intended to run within QEMU environment.
+//
+// Usage 1: reliability_test
+// Upon invocation, it visits a hard coded list of URLs. This is mainly used
+// by buildbot, to verify reliability_test itself runs ok.
+//
+// Usage 2: reliability_test --site=url --startpage=start --endpage=end [...]
+// Upon invocation, it visits a list of URLs constructed as
+// "http://url/page?id=k". (start <= k <= end).
+//
+// Usage 3: reliability_test --list=file --startline=start --endline=end [...]
+// Upon invocation, it visits each of the URLs on line numbers between start
+// and end, inclusive, stored in the input file. The line number starts from 1.
+//
+// If both "--site" and "--list" are provided, the "--site" set of arguments
+// are ignored.
+//
+// Optional Switches:
+// --iterations=num: goes through the list of URLs constructed in usage 2 or 3
+// num times.
+// --continuousload: continuously visits the list of URLs without restarting
+// browser for each page load.
+// --memoryusage: prints out memory usage when visiting each page.
+// --endurl=url: visits the specified url in the end.
+// --logfile=filepath: saves the visit log to the specified path.
+// --timeout=millisecond: time out as specified in millisecond during each
+// page load.
+// --nopagedown: won't simulate page down key presses after page load.
+
+#include <fstream>
+#include <iostream>
+
+#include "base/command_line.h"
+#include "base/file_util.h"
+#include "base/path_service.h"
+#include "base/string_util.h"
+#include "chrome/browser/url_fixer_upper.h"
+#include "chrome/common/chrome_constants.h"
+#include "chrome/common/chrome_paths.h"
+#include "chrome/common/pref_names.h"
+#include "chrome/common/pref_service.h"
+#include "chrome/test/automation/automation_messages.h"
+#include "chrome/test/automation/automation_proxy.h"
+#include "chrome/test/automation/browser_proxy.h"
+#include "chrome/test/automation/tab_proxy.h"
+#include "chrome/test/automation/window_proxy.h"
+#include "chrome/test/ui/ui_test.h"
+#include "chrome/test/perf/mem_usage.h"
+#include "chrome/test/reliability/page_load_test.h"
+#include "net/base/net_util.h"
+
+namespace {
+
+// See comments at the beginning of the file for the definition of switches.
+const wchar_t kSiteSwitch[] = L"site";
+const wchar_t kStartPageSwitch[] = L"startpage";
+const wchar_t kEndPageSwitch[] = L"endpage";
+const wchar_t kListSwitch[] = L"list";
+const wchar_t kStartIndexSwitch[] = L"startline";
+const wchar_t kEndIndexSwitch[] = L"endline";
+const wchar_t kIterationSwitch[] = L"iterations";
+const wchar_t kContinuousLoadSwitch[] = L"continuousload";
+const wchar_t kMemoryUsageSwitch[] = L"memoryusage";
+const wchar_t kEndURLSwitch[] = L"endurl";
+const wchar_t kLogFileSwitch[] = L"logfile";
+const wchar_t kTimeoutSwitch[] = L"timeout";
+const wchar_t kNoPageDownSwitch[] = L"nopagedown";
+
+std::wstring server_url = L"http://urllist.com";
+const wchar_t test_url_1[] = L"http://www.google.com";
+const wchar_t test_url_2[] = L"about:crash";
+const wchar_t test_url_3[] = L"http://www.youtube.com";
+bool append_page_id = false;
+int32 start_page;
+int32 end_page;
+std::wstring url_file_path;
+int32 start_index = 1;
+int32 end_index = kint32max;
+int32 iterations = 1;
+bool memory_usage = false;
+bool continuous_load = false;
+bool browser_existing = false;
+bool page_down = true;
+std::wstring end_url;
+std::wstring log_file_path;
+uint32 timeout_ms = INFINITE;
+
+int kWaitForActionMsec = 4000;
+
+class PageLoadTest : public UITest {
+ public:
+ enum NavigationResult {
+ NAVIGATION_ERROR = 0,
+ NAVIGATION_SUCCESS,
+ NAVIGATION_AUTH_NEEDED,
+ NAVIGATION_TIME_OUT,
+ };
+
+ typedef struct {
+ // These are results from the test automation that drives Chrome
+ NavigationResult result;
+ int crash_dump_count;
+ // These are stability metrics recorded by Chrome itself
+ bool browser_clean_exit;
+ int browser_launch_count;
+ int page_load_count;
+ int browser_crash_count;
+ int renderer_crash_count;
+ int plugin_crash_count;
+ } NavigationMetrics;
+
+ PageLoadTest() {
+ show_window_ = true;
+ }
+
+ void NavigateToURLLogResult(const GURL& url, std::ofstream& log_file,
+ NavigationMetrics* metrics_output) {
+ NavigationMetrics metrics = {NAVIGATION_ERROR};
+
+ if (!continuous_load && !browser_existing) {
+ LaunchBrowserAndServer();
+ browser_existing = true;
+ }
+
+ bool is_timeout = false;
+ int result = AUTOMATION_MSG_NAVIGATION_ERROR;
+ // This is essentially what NavigateToURL does except we don't fire
+ // assertion when page loading fails. We log the result instead.
+ {
+ // TabProxy should be released before Browser is closed.
+ scoped_ptr<TabProxy> tab_proxy(GetActiveTab());
+ if (tab_proxy.get()) {
+ result = tab_proxy->NavigateToURLWithTimeout(url, timeout_ms,
+ &is_timeout);
+ }
+
+ if (!is_timeout && result == AUTOMATION_MSG_NAVIGATION_SUCCESS) {
+ if (page_down) {
+ // Page down twice.
+ scoped_ptr<BrowserProxy> browser(automation()->GetBrowserWindow(0));
+ if (browser.get()) {
+ scoped_ptr<WindowProxy> window(
+ automation()->GetWindowForBrowser(browser.get()));
+ if (window.get()) {
+ bool activation_timeout;
+ browser->BringToFrontWithTimeout(kWaitForActionMsec,
+ &activation_timeout);
+ if (!activation_timeout) {
+ window->SimulateOSKeyPress(VK_NEXT, 0);
+ Sleep(kWaitForActionMsec);
+ window->SimulateOSKeyPress(VK_NEXT, 0);
+ Sleep(kWaitForActionMsec);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (!continuous_load) {
+ CloseBrowserAndServer();
+ browser_existing = false;
+ }
+
+ // Get navigation result and metrics, and optionally write to the log file
+ // provided. The log format is:
+ // <url> <navigation_result> <browser_crash_count> <renderer_crash_count>
+ // <plugin_crash_count> <crash_dump_count> crash_dump=<path>
+ if (is_timeout) {
+ metrics.result = NAVIGATION_TIME_OUT;
+ // After timeout, the test automation is in the transition state since
+ // there might be pending IPC messages and the browser (automation
+ // provider) is still working on the request. Here we just skip the url
+ // and send the next request. The pending IPC messages will be properly
+ // discarded by automation message filter. The browser will accept the
+ // new request and visit the next URL.
+ // We will revisit the issue if we encounter the situation where browser
+ // needs to be restarted after timeout.
+ } else {
+ switch (result) {
+ case AUTOMATION_MSG_NAVIGATION_ERROR:
+ metrics.result = NAVIGATION_ERROR;
+ break;
+ case AUTOMATION_MSG_NAVIGATION_SUCCESS:
+ metrics.result = NAVIGATION_SUCCESS;
+ break;
+ case AUTOMATION_MSG_NAVIGATION_AUTH_NEEDED:
+ metrics.result = NAVIGATION_AUTH_NEEDED;
+ break;
+ default:
+ metrics.result = NAVIGATION_ERROR;
+ break;
+ }
+ }
+
+ if (log_file.is_open()) {
+ log_file << url.spec();
+ switch (metrics.result) {
+ case NAVIGATION_ERROR:
+ log_file << " error";
+ break;
+ case NAVIGATION_SUCCESS:
+ log_file << " success";
+ break;
+ case NAVIGATION_AUTH_NEEDED:
+ log_file << " auth_needed";
+ break;
+ case NAVIGATION_TIME_OUT:
+ log_file << " timeout";
+ break;
+ default:
+ break;
+ }
+ }
+
+ // Get stability metrics recorded by Chrome itself.
+ GetStabilityMetrics(&metrics);
+
+ if (log_file.is_open()) {
+ log_file << " " << metrics.browser_crash_count \
+ // The renderer crash count is flaky due to 1183283.
+ // Ignore the count since we also catch crash by
+ // crash_dump_count.
+ << " " << 0 \
+ << " " << metrics.plugin_crash_count \
+ << " " << metrics.crash_dump_count;
+ }
+
+ // Get crash dumps.
+ LogOrDeleteNewCrashDumps(log_file, &metrics);
+
+ if (log_file.is_open()) {
+ log_file << std::endl;
+ }
+
+ if (metrics_output) {
+ *metrics_output = metrics;
+ }
+ }
+
+ void NavigateThroughPageID(std::ofstream& log_file) {
+ if (append_page_id) {
+ // For usage 2
+ for (int i = start_page; i <= end_page; ++i) {
+ std::wstring test_page_url(
+ StringPrintf(L"%s/page?id=%d", server_url.c_str(), i));
+ NavigateToURLLogResult(GURL(test_page_url), log_file, NULL);
+ }
+ } else {
+ // Don't run if single process mode.
+ if (in_process_renderer())
+ return;
+ // For usage 1
+ NavigationMetrics metrics;
+ if (timeout_ms == INFINITE)
+ timeout_ms = 30000;
+
+ NavigateToURLLogResult(GURL(test_url_1), log_file, &metrics);
+ // Verify everything is fine
+ EXPECT_EQ(NAVIGATION_SUCCESS, metrics.result);
+ EXPECT_EQ(0, metrics.crash_dump_count);
+ EXPECT_EQ(true, metrics.browser_clean_exit);
+ EXPECT_EQ(1, metrics.browser_launch_count);
+ // Both starting page and test_url_1 are loaded.
+ EXPECT_EQ(2, metrics.page_load_count);
+ EXPECT_EQ(0, metrics.browser_crash_count);
+ EXPECT_EQ(0, metrics.renderer_crash_count);
+ EXPECT_EQ(0, metrics.plugin_crash_count);
+
+ // Go to "about:crash"
+ uint32 crash_timeout_ms = timeout_ms / 2;
+ std::swap(timeout_ms, crash_timeout_ms);
+ NavigateToURLLogResult(GURL(test_url_2), log_file, &metrics);
+ std::swap(timeout_ms, crash_timeout_ms);
+ // Page load crashed and test automation timed out.
+ EXPECT_EQ(NAVIGATION_TIME_OUT, metrics.result);
+ // Found a crash dump
+ EXPECT_EQ(1, metrics.crash_dump_count);
+ // Browser did not crash, and exited cleanly.
+ EXPECT_EQ(true, metrics.browser_clean_exit);
+ EXPECT_EQ(1, metrics.browser_launch_count);
+ // Only starting page was loaded.
+ EXPECT_EQ(1, metrics.page_load_count);
+ EXPECT_EQ(0, metrics.browser_crash_count);
+ // Renderer crashed.
+ EXPECT_EQ(1, metrics.renderer_crash_count);
+ EXPECT_EQ(0, metrics.plugin_crash_count);
+
+ uint32 youtube_timeout_ms = timeout_ms * 2;
+ std::swap(timeout_ms, youtube_timeout_ms);
+ NavigateToURLLogResult(GURL(test_url_3), log_file, &metrics);
+ std::swap(timeout_ms, youtube_timeout_ms);
+ // The data on previous crash should be cleared and we should get
+ // metrics for a successful page load.
+ EXPECT_EQ(NAVIGATION_SUCCESS, metrics.result);
+ EXPECT_EQ(0, metrics.crash_dump_count);
+ EXPECT_EQ(true, metrics.browser_clean_exit);
+ EXPECT_EQ(1, metrics.browser_launch_count);
+ EXPECT_EQ(0, metrics.browser_crash_count);
+ EXPECT_EQ(0, metrics.renderer_crash_count);
+ EXPECT_EQ(0, metrics.plugin_crash_count);
+
+ // Verify metrics service does what we need when browser process crashes.
+ HANDLE browser_process;
+ LaunchBrowserAndServer();
+ {
+ // TabProxy should be released before Browser is closed.
+ scoped_ptr<TabProxy> tab_proxy(GetActiveTab());
+ if (tab_proxy.get()) {
+ tab_proxy->NavigateToURL(GURL(test_url_1));
+ }
+ }
+ // Kill browser process.
+ browser_process = process();
+ TerminateProcess(browser_process, 0);
+
+ GetStabilityMetrics(&metrics);
+ // This is not a clean shutdown.
+ EXPECT_EQ(false, metrics.browser_clean_exit);
+ EXPECT_EQ(1, metrics.browser_crash_count);
+ EXPECT_EQ(0, metrics.renderer_crash_count);
+ EXPECT_EQ(0, metrics.plugin_crash_count);
+ // Relaunch browser so UITest does not fire assertion during TearDown.
+ LaunchBrowserAndServer();
+ }
+ }
+
+ // For usage 3
+ void NavigateThroughURLList(std::ofstream& log_file) {
+ std::ifstream file(url_file_path.c_str());
+ ASSERT_TRUE(file.is_open());
+
+ for (int line_index = 1;
+ line_index <= end_index && !file.eof();
+ ++line_index) {
+ std::string url_str;
+ std::getline(file, url_str);
+
+ if (file.fail())
+ break;
+
+ if (start_index <= line_index) {
+ NavigateToURLLogResult(GURL(url_str), log_file, NULL);
+ }
+ }
+
+ file.close();
+ }
+
+ protected:
+ // Call the base class's SetUp method and initialize our own class members.
+ virtual void SetUp() {
+ UITest::SetUp();
+ browser_existing = true;
+
+ // Initialize crash_dumps_dir_path_.
+ PathService::Get(chrome::DIR_CRASH_DUMPS, &crash_dumps_dir_path_);
+ // Initialize crash_dumps_.
+ WIN32_FIND_DATAW find_data;
+ HANDLE find_handle;
+ std::wstring dir_spec(crash_dumps_dir_path_);
+ dir_spec.append(L"\\*"); // list all files in the directory
+ find_handle = FindFirstFileW(dir_spec.c_str(), &find_data);
+ if (find_handle != INVALID_HANDLE_VALUE) {
+ if (wcsstr(find_data.cFileName, L".dmp"))
+ crash_dumps_[std::wstring(find_data.cFileName)] = true;
+ while (FindNextFile(find_handle, &find_data)) {
+ if (wcsstr(find_data.cFileName, L".dmp"))
+ crash_dumps_[std::wstring(find_data.cFileName)] = true;
+ }
+ FindClose(find_handle);
+ }
+ }
+
+ // If a log_file is provided, log the crash dump with the given path;
+ // otherwise, delete the crash dump file.
+ void LogOrDeleteCrashDump(std::ofstream& log_file,
+ std::wstring crash_dump_file_name) {
+
+ std::wstring crash_dump_file_path(crash_dumps_dir_path_);
+ crash_dump_file_path.append(L"\\");
+ crash_dump_file_path.append(crash_dump_file_name);
+ std::wstring crash_text_file_path(crash_dump_file_path);
+ crash_text_file_path.replace(crash_text_file_path.length() - 3,
+ 3, L"txt");
+
+ if (log_file.is_open()) {
+ crash_dumps_[crash_dump_file_name] = true;
+ log_file << " crash_dump=" << crash_dump_file_path;
+ } else {
+ ASSERT_TRUE(DeleteFileW(crash_dump_file_path.c_str()));
+ ASSERT_TRUE(DeleteFileW(crash_text_file_path.c_str()));
+ }
+ }
+
+ // Check whether there are new .dmp files. Additionally, write
+ // " crash_dump=<full path name of the .dmp file>"
+ // to log_file.
+ void LogOrDeleteNewCrashDumps(std::ofstream& log_file,
+ NavigationMetrics* metrics) {
+ WIN32_FIND_DATAW find_data;
+ HANDLE find_handle;
+ int num_dumps = 0;
+
+ std::wstring dir_spec(crash_dumps_dir_path_);
+ dir_spec.append(L"\\*"); // list all files in the directory
+ find_handle = FindFirstFileW(dir_spec.c_str(), &find_data);
+ if (find_handle != INVALID_HANDLE_VALUE) {
+ if (wcsstr(find_data.cFileName, L".dmp") &&
+ !crash_dumps_[std::wstring(find_data.cFileName)]) {
+ LogOrDeleteCrashDump(log_file, find_data.cFileName);
+ num_dumps++;
+ }
+ while (FindNextFile(find_handle, &find_data)) {
+ if (wcsstr(find_data.cFileName, L".dmp") &&
+ !crash_dumps_[std::wstring(find_data.cFileName)]) {
+ LogOrDeleteCrashDump(log_file, find_data.cFileName);
+ num_dumps++;
+ }
+ }
+ FindClose(find_handle);
+ }
+
+ if (metrics)
+ metrics->crash_dump_count = num_dumps;
+ }
+
+ // Get a PrefService whose contents correspond to the Local State file
+ // that was saved by the app as it closed. The caller takes ownership of the
+ // returned PrefService object.
+ PrefService* GetLocalState() {
+ std::wstring local_state_path = user_data_dir();
+ file_util::AppendToPath(&local_state_path, chrome::kLocalStateFilename);
+
+ PrefService* local_state(new PrefService(local_state_path));
+ return local_state;
+ }
+
+ void GetStabilityMetrics(NavigationMetrics* metrics) {
+ if (!metrics)
+ return;
+ scoped_ptr<PrefService> local_state(GetLocalState());
+ if (!local_state.get())
+ return;
+ local_state->RegisterBooleanPref(prefs::kStabilityExitedCleanly, false);
+ local_state->RegisterIntegerPref(prefs::kStabilityLaunchCount, -1);
+ local_state->RegisterIntegerPref(prefs::kStabilityPageLoadCount, -1);
+ local_state->RegisterIntegerPref(prefs::kStabilityCrashCount, 0);
+ local_state->RegisterIntegerPref(prefs::kStabilityRendererCrashCount, 0);
+
+ metrics->browser_clean_exit =
+ local_state->GetBoolean(prefs::kStabilityExitedCleanly);
+ metrics->browser_launch_count =
+ local_state->GetInteger(prefs::kStabilityLaunchCount);
+ metrics->page_load_count =
+ local_state->GetInteger(prefs::kStabilityPageLoadCount);
+ metrics->browser_crash_count =
+ local_state->GetInteger(prefs::kStabilityCrashCount);
+ metrics->renderer_crash_count =
+ local_state->GetInteger(prefs::kStabilityRendererCrashCount);
+ // TODO(huanr)
+ metrics->plugin_crash_count = 0;
+
+ if (!metrics->browser_clean_exit)
+ metrics->browser_crash_count++;
+ }
+
+ // The pathname of Chrome's crash dumps directory.
+ std::wstring crash_dumps_dir_path_;
+
+ // The set of all the crash dumps we have seen. Each crash generates a
+ // .dmp and a .txt file in the crash dumps directory. We only store the
+ // .dmp files in this set.
+ //
+ // The set is implemented as a std::map. The key is the file name, and
+ // the value is false (the file is not in the set) or true (the file is
+ // in the set). The initial value for any key in std::map is 0 (false),
+ // which in this case means a new file is not in the set initially,
+ // exactly the semantics we want.
+ std::map<std::wstring, bool> crash_dumps_;
+};
+
+} // namespace
+
+TEST_F(PageLoadTest, Reliability) {
+ std::ofstream log_file;
+
+ if (!log_file_path.empty()) {
+ log_file.open(log_file_path.c_str());
+ }
+
+ for (int k = 0; k < iterations; ++k) {
+ if (url_file_path.empty()) {
+ NavigateThroughPageID(log_file);
+ } else {
+ NavigateThroughURLList(log_file);
+ }
+
+ if (memory_usage)
+ PrintChromeMemoryUsageInfo();
+ }
+
+ if (!end_url.empty()) {
+ NavigateToURLLogResult(GURL(end_url), log_file, NULL);
+ }
+
+ log_file.close();
+}
+
+void SetPageRange(const CommandLine& parsed_command_line) {
+ if (parsed_command_line.HasSwitch(kStartPageSwitch)) {
+ ASSERT_TRUE(parsed_command_line.HasSwitch(kEndPageSwitch));
+ start_page =
+ _wtoi(parsed_command_line.GetSwitchValue(kStartPageSwitch).c_str());
+ end_page =
+ _wtoi(parsed_command_line.GetSwitchValue(kEndPageSwitch).c_str());
+ ASSERT_TRUE(start_page > 0 && end_page > 0);
+ ASSERT_TRUE(start_page < end_page);
+ append_page_id = true;
+ } else {
+ ASSERT_FALSE(parsed_command_line.HasSwitch(kEndPageSwitch));
+ }
+
+ if (parsed_command_line.HasSwitch(kSiteSwitch))
+ server_url.assign(parsed_command_line.GetSwitchValue(kSiteSwitch));
+
+ if (parsed_command_line.HasSwitch(kStartIndexSwitch)) {
+ start_index =
+ _wtoi(parsed_command_line.GetSwitchValue(kStartIndexSwitch).c_str());
+ ASSERT_TRUE(start_index > 0);
+ }
+
+ if (parsed_command_line.HasSwitch(kEndIndexSwitch)) {
+ end_index =
+ _wtoi(parsed_command_line.GetSwitchValue(kEndIndexSwitch).c_str());
+ ASSERT_TRUE(end_index > 0);
+ }
+
+ ASSERT_TRUE(end_index >= start_index);
+
+ if (parsed_command_line.HasSwitch(kListSwitch))
+ url_file_path.assign(parsed_command_line.GetSwitchValue(kListSwitch));
+
+ if (parsed_command_line.HasSwitch(kIterationSwitch)) {
+ iterations =
+ _wtoi(parsed_command_line.GetSwitchValue(kIterationSwitch).c_str());
+ ASSERT_TRUE(iterations > 0);
+ }
+
+ if (parsed_command_line.HasSwitch(kMemoryUsageSwitch))
+ memory_usage = true;
+
+ if (parsed_command_line.HasSwitch(kContinuousLoadSwitch))
+ continuous_load = true;
+
+ if (parsed_command_line.HasSwitch(kEndURLSwitch))
+ end_url.assign(parsed_command_line.GetSwitchValue(kEndURLSwitch));
+
+ if (parsed_command_line.HasSwitch(kLogFileSwitch))
+ log_file_path.assign(parsed_command_line.GetSwitchValue(kLogFileSwitch));
+
+ if (parsed_command_line.HasSwitch(kTimeoutSwitch)) {
+ timeout_ms =
+ _wtoi(parsed_command_line.GetSwitchValue(kTimeoutSwitch).c_str());
+ ASSERT_TRUE(timeout_ms > 0);
+ }
+
+ if (parsed_command_line.HasSwitch(kNoPageDownSwitch))
+ page_down = false;
+}
diff --git a/chrome/test/reliability/page_load_test.h b/chrome/test/reliability/page_load_test.h
new file mode 100644
index 0000000..8f3c2da
--- /dev/null
+++ b/chrome/test/reliability/page_load_test.h
@@ -0,0 +1,41 @@
+// 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.
+//
+// This file declares helper functions necessary to run reliablity test under
+// UI test framework.
+
+#ifndef CHROME_TEST_RELIABILITY_PAGE_LOAD_TEST_H__
+#define CHROME_TEST_RELIABILITY_PAGE_LOAD_TEST_H__
+
+#include "base/command_line.h"
+
+// Parse the command line options and set the page range accordingly.
+void SetPageRange(const CommandLine&);
+
+#endif // CHROME_TEST_RELIABILITY_PAGE_LOAD_TEST_H__
diff --git a/chrome/test/reliability/reliability_test_suite.h b/chrome/test/reliability/reliability_test_suite.h
new file mode 100644
index 0000000..1e971e6
--- /dev/null
+++ b/chrome/test/reliability/reliability_test_suite.h
@@ -0,0 +1,50 @@
+// 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.
+
+#ifndef CHROME_TEST_RELIABILITY_RELIABILITY_TEST_SUITE_H_
+#define CHROME_TEST_RELIABILITY_RELIABILITY_TEST_SUITE_H_
+
+#include "chrome/test/reliability/page_load_test.h"
+#include "chrome/test/ui/ui_test_suite.h"
+
+class ReliabilityTestSuite : public UITestSuite {
+public:
+ ReliabilityTestSuite(int argc, char** argv) : UITestSuite(argc, argv) {
+ }
+
+protected:
+
+ virtual void Initialize() {
+ UITestSuite::Initialize();
+
+ SetPageRange(parsed_command_line_);
+ }
+};
+
+#endif // CHROME_TEST_RELIABILITY_RELIABILITY_TEST_SUITE_H_
diff --git a/chrome/test/reliability/reliability_tests.vcproj b/chrome/test/reliability/reliability_tests.vcproj
new file mode 100644
index 0000000..04f0ef9
--- /dev/null
+++ b/chrome/test/reliability/reliability_tests.vcproj
@@ -0,0 +1,218 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="reliability_tests"
+ ProjectGUID="{8A3E1774-1DE9-445C-982D-3EE37C8A752A}"
+ RootNamespace="reliability_tests"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ ConfigurationType="1"
+ InheritedPropertySheets="$(SolutionDir)..\build\common.vsprops;$(SolutionDir)..\build\debug.vsprops;..\..\tools\build\win\precompiled_wtl.vsprops;..\..\tools\build\win\unit_test.vsprops;..\..\tools\build\win\ui_test.vsprops;..\..\tools\build\win\test_memory_usage.vsprops;..\..\tools\build\win\reliability_test.vsprops;$(SolutionDir)..\skia\using_skia.vsprops;$(SolutionDir)..\testing\using_gtest.vsprops"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="winmm.lib"
+ />
+ <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"
+ ConfigurationType="1"
+ InheritedPropertySheets="$(SolutionDir)..\build\common.vsprops;$(SolutionDir)..\build\release.vsprops;..\..\tools\build\win\unit_test.vsprops;..\..\tools\build\win\ui_test.vsprops;..\..\tools\build\win\test_memory_usage.vsprops;..\..\tools\build\win\reliability_test.vsprops;$(SolutionDir)..\skia\using_skia.vsprops;$(SolutionDir)..\testing\using_gtest.vsprops"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="winmm.lib"
+ />
+ <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="Common"
+ >
+ <File
+ RelativePath="..\..\tools\build\win\precompiled_wtl.cc"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="1"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\tools\build\win\precompiled_wtl.h"
+ >
+ </File>
+ <File
+ RelativePath=".\reliability_test_suite.h"
+ >
+ </File>
+ <File
+ RelativePath=".\run_all_unittests.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\test_file_util.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\testing_browser_process.h"
+ >
+ </File>
+ <File
+ RelativePath="..\ui\ui_test.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\ui\ui_test.h"
+ >
+ </File>
+ <File
+ RelativePath="..\ui\ui_test_suite.cc"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="MemoryUsage"
+ >
+ <File
+ RelativePath="..\perf\mem_usage.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\perf\mem_usage.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="TestPageLoader"
+ >
+ <File
+ RelativePath=".\page_load_test.cc"
+ >
+ </File>
+ <File
+ RelativePath=".\page_load_test.h"
+ >
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/chrome/test/reliability/run_all_unittests.cc b/chrome/test/reliability/run_all_unittests.cc
new file mode 100644
index 0000000..a5d3da3
--- /dev/null
+++ b/chrome/test/reliability/run_all_unittests.cc
@@ -0,0 +1,34 @@
+// 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.
+
+#include "chrome/test/reliability/reliability_test_suite.h"
+
+int main(int argc, char **argv) {
+ return ReliabilityTestSuite(argc, argv).Run();
+}
diff --git a/chrome/test/security_tests/SConscript b/chrome/test/security_tests/SConscript
new file mode 100644
index 0000000..39300c8
--- /dev/null
+++ b/chrome/test/security_tests/SConscript
@@ -0,0 +1,91 @@
+# 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.
+
+Import('env')
+
+env = env.Clone()
+
+
+env.Prepend(
+ CPPPATH = [
+ '#/..',
+ ],
+ LINKFLAGS = [
+ '/INCREMENTAL',
+
+ '/MANIFEST',
+ '/DELAYLOAD:"dwmapi.dll"',
+ '/DELAYLOAD:"uxtheme.dll"',
+ '/MACHINE:X86',
+ '/FIXED:No',
+
+ '/safeseh',
+ '/dynamicbase',
+ '/ignore:4199',
+ '/nxcompat',
+
+ '/DEBUG',
+ ],
+ LIBS = [
+ 'wininet.lib',
+ 'version.lib',
+ 'msimg32.lib',
+ 'ws2_32.lib',
+ 'usp10.lib',
+ 'psapi.lib',
+ 'kernel32.lib',
+ 'user32.lib',
+ 'gdi32.lib',
+ 'winspool.lib',
+ 'comdlg32.lib',
+ 'advapi32.lib',
+ 'shell32.lib',
+ 'ole32.lib',
+ 'oleaut32.lib',
+ 'uuid.lib',
+ 'odbc32.lib',
+ 'odbccp32.lib',
+
+ 'DelayImp.lib',
+ ],
+)
+
+#/MANIFESTFILE:"C:\src\trunk-vs\chrome\Debug\obj\test_chrome_plugin\test_chrome_plugin.dll.intermediate.manifest"
+#/PDB:"c:\src\trunk-vs\chrome\Debug\test_chrome_plugin.pdb"
+
+input_files = [
+ 'ipc_security_tests.cc',
+ 'security_tests.cc',
+ '$SANDBOX_DIR/tests/validation_tests/commands${OBJSUFFIX}',
+]
+
+dll = env.SharedLibrary('security_tests', input_files)
+
+i = env.Install('$TARGET_ROOT', dll)
+env.Alias('chrome', i)
diff --git a/chrome/test/security_tests/ipc_security_tests.cc b/chrome/test/security_tests/ipc_security_tests.cc
new file mode 100644
index 0000000..e85e09b
--- /dev/null
+++ b/chrome/test/security_tests/ipc_security_tests.cc
@@ -0,0 +1,217 @@
+// 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.
+
+#include <windows.h>
+#include <string>
+#include <sstream>
+
+#include "chrome/test/security_tests/ipc_security_tests.h"
+
+namespace {
+
+// Debug output messages prefix.
+const char kODSMgPrefix[] = "[security] ";
+// Format of the Chrome browser pipe for plugins.
+const wchar_t kChromePluginPipeFmt[] = L"\\\\.\\pipe\\chrome.%s.p%d";
+// Size for the in/out pipe buffers.
+const int kBufferSize = 1024;
+
+// Define the next symbol if you want to have tracing of errors.
+#ifdef PIPE_SECURITY_DBG
+// Generic debug output function.
+void ODSMessageGLE(const char* txt) {
+ DWORD gle = ::GetLastError();
+ std::ostringstream oss;
+ oss << kODSMgPrefix << txt << " 0x" << std::hex << gle;
+ ::OutputDebugStringA(oss.str().c_str());
+}
+#else
+void ODSMessageGLE(const char* txt) {
+}
+#endif
+
+// Retrieves the renderer pipe name from the command line. Returns true if the
+// name was found.
+bool PipeNameFromCommandLine(std::wstring* pipe_name) {
+ std::wstring cl(::GetCommandLineW());
+ const wchar_t key_name[] = L"--channel";
+ std::wstring::size_type pos = cl.find(key_name, 0);
+ if (std::wstring::npos == pos) {
+ return false;
+ }
+ pos = cl.find(L"=", pos);
+ if (std::wstring::npos == pos) {
+ return false;
+ }
+ ++pos;
+ size_t dst = cl.length() - pos;
+ if (dst <4) {
+ return false;
+ }
+ for (; dst != 0; --dst) {
+ if (!isspace(cl[pos])) {
+ break;
+ }
+ ++pos;
+ }
+ if (0 == dst) {
+ return false;
+ }
+ std::wstring::size_type pos2 = pos;
+ for (; dst != 0; --dst) {
+ if (isspace(cl[pos2])) {
+ break;
+ }
+ ++pos2;
+ }
+ *pipe_name = cl.substr(pos, pos2);
+ return true;
+}
+
+// Extracts the browser process id and the channel id given the renderer
+// pipe name.
+bool InfoFromPipeName(const std::wstring& pipe_name, std::wstring* parent_id,
+ std::wstring* channel_id) {
+ std::wstring::size_type pos = pipe_name.find(L".", 0);
+ if (std::wstring::npos == pos) {
+ return false;
+ }
+ *parent_id = pipe_name.substr(0, pos);
+ *channel_id = pipe_name.substr(pos + 1);
+ return true;
+}
+
+// Creates a server pipe, in byte mode.
+HANDLE MakeServerPipeBase(const wchar_t* pipe_name) {
+ HANDLE pipe = ::CreateNamedPipeW(pipe_name, PIPE_ACCESS_DUPLEX,
+ PIPE_TYPE_BYTE | PIPE_READMODE_BYTE, 3,
+ kBufferSize, kBufferSize, 5000, NULL);
+ if (INVALID_HANDLE_VALUE == pipe) {
+ ODSMessageGLE("pipe creation failed");
+ }
+ return pipe;
+}
+
+// Creates a chrome plugin server pipe.
+HANDLE MakeServerPluginPipe(const std::wstring& prefix, int channel) {
+ wchar_t pipe_name[MAX_PATH];
+ swprintf_s(pipe_name, kChromePluginPipeFmt, prefix.c_str(), channel);
+ return MakeServerPipeBase(pipe_name);
+}
+
+struct Context {
+ HANDLE pipe;
+ Context(HANDLE arg_pipe) : pipe(arg_pipe) {
+ }
+};
+
+// This function is called from a thread that has a security context that is
+// higher than the renderer security context. This can be the plugin security
+// context or the browser security context.
+void DoEvilThings(Context* context) {
+ // To make the test fail we simply trigger a breakpoint in the renderer.
+ ::DisconnectNamedPipe(context->pipe);
+ __debugbreak();
+}
+
+// This is a pipe server thread routine.
+DWORD WINAPI PipeServerProc(void* thread_param) {
+ if (NULL == thread_param) {
+ return 0;
+ }
+ Context* context = static_cast<Context*>(thread_param);
+ HANDLE server_pipe = context->pipe;
+
+ char buffer[4];
+ DWORD bytes_read = 0;
+
+ for (;;) {
+ // The next call blocks until a connection is made.
+ if (!::ConnectNamedPipe(server_pipe, NULL)) {
+ if (GetLastError() != ERROR_PIPE_CONNECTED) {
+ ODSMessageGLE("== connect named pipe failed ==");
+ continue;
+ }
+ }
+ // return value of ReadFile is unimportant.
+ ::ReadFile(server_pipe, buffer, 1, &bytes_read, NULL);
+ if (::ImpersonateNamedPipeClient(server_pipe)) {
+ ODSMessageGLE("impersonation obtained");
+ DoEvilThings(context);
+ break;
+ } else {
+ ODSMessageGLE("impersonation failed");
+ }
+ ::DisconnectNamedPipe(server_pipe);
+ }
+ delete context;
+ return 0;
+}
+} // namespace
+
+// Implements a pipe impersonation attack resulting on a privilege elevation on
+// the chrome pipe-based IPC.
+// When a web-page that has a plug-in is loaded, chrome will do the following
+// steps:
+// 1) Creates a server pipe with name 'chrome.<pid>.p<n>'. Initially n = 1.
+// 2) Launches chrome with command line --type=plugin --channel=<pid>.p<n>
+// 3) The new (plugin) process connects to the pipe and sends a 'hello'
+// message.
+// The attack creates another server pipe with the same name before step one
+// so when the plugin connects it connects to the renderer instead. Once the
+// connection is acepted and at least a byte is read from the pipe, the
+// renderer can impersonate the plugin process which has a more relaxed
+// security context (privilege elevation).
+//
+// Note that the attack can also be peformed after step 1. In this case we need
+// another thread which used to connect to the existing server pipe so the
+// plugin does not connect to chrome but to our pipe.
+bool PipeImpersonationAttack() {
+ std::wstring pipe_name;
+ if (!PipeNameFromCommandLine(&pipe_name)) {
+ return false;
+ }
+ std::wstring parent_id;
+ std::wstring channel_id;
+ if (!InfoFromPipeName(pipe_name, &parent_id, &channel_id)) {
+ return false;
+ }
+ HANDLE plugin_pipe = MakeServerPluginPipe(parent_id, 1);
+ if (INVALID_HANDLE_VALUE == plugin_pipe) {
+ return true;
+ }
+
+ HANDLE thread = ::CreateThread(NULL, 0, PipeServerProc,
+ new Context(plugin_pipe), 0, NULL);
+ if (NULL == thread) {
+ return false;
+ }
+ ::CloseHandle(thread);
+ return true;
+}
diff --git a/chrome/test/security_tests/ipc_security_tests.h b/chrome/test/security_tests/ipc_security_tests.h
new file mode 100644
index 0000000..8706570
--- /dev/null
+++ b/chrome/test/security_tests/ipc_security_tests.h
@@ -0,0 +1,39 @@
+// 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.
+
+#ifndef CHROME_TEST_SECURITY_TESTS_IPC_SECURITY_TESTS_H__
+#define CHROME_TEST_SECURITY_TESTS_IPC_SECURITY_TESTS_H__
+
+// Impersonates a chrome server pipe. See the implementation for details.
+// Returns false if the attack could not be set. If it returns true then
+// it spawns a thread that will terminate the renderer if the attack is
+// successful.
+bool PipeImpersonationAttack();
+
+#endif // CHROME_TEST_SECURITY_TESTS_IPC_SECURITY_TESTS_H__
diff --git a/chrome/test/security_tests/security_tests.cc b/chrome/test/security_tests/security_tests.cc
new file mode 100644
index 0000000..e86df13
--- /dev/null
+++ b/chrome/test/security_tests/security_tests.cc
@@ -0,0 +1,87 @@
+// 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.
+
+#include <windows.h>
+#include <string>
+
+#define TEST_INJECTION_DLL
+#include "chrome/test/injection_test_dll.h"
+#include "chrome/test/security_tests/ipc_security_tests.h"
+#include "sandbox/tests/common/controller.h"
+#include "sandbox/tests/validation_tests/commands.h"
+
+#define SECURITY_CHECK(x) (*test_count)++; \
+ if (SBOX_TEST_DENIED != x) { \
+ return FALSE; \
+ };
+
+BOOL APIENTRY DllMain(HMODULE module, DWORD ul_reason_for_call,
+ LPVOID lpReserved) {
+ return TRUE;
+}
+
+// Runs the security tests of sandbox for the renderer process.
+// If a test fails, the return value is FALSE and test_count contains the
+// number of tests executed, including the failing test.
+BOOL __declspec(dllexport) __cdecl RunRendererTests(int *test_count) {
+ using namespace sandbox;
+ *test_count = 0;
+ SECURITY_CHECK(TestOpenReadFile(L"%SystemDrive%"));
+ SECURITY_CHECK(TestOpenReadFile(L"%SystemRoot%"));
+ SECURITY_CHECK(TestOpenReadFile(L"%ProgramFiles%"));
+ SECURITY_CHECK(TestOpenReadFile(L"%SystemRoot%\\System32"));
+ SECURITY_CHECK(TestOpenReadFile(L"%SystemRoot%\\explorer.exe"));
+ SECURITY_CHECK(TestOpenReadFile(L"%SystemRoot%\\Cursors\\arrow_i.cur"));
+ SECURITY_CHECK(TestOpenReadFile(L"%AllUsersProfile%"));
+ SECURITY_CHECK(TestOpenReadFile(L"%Temp%"));
+ SECURITY_CHECK(TestOpenReadFile(L"%AppData%"));
+ SECURITY_CHECK(TestOpenKey(HKEY_LOCAL_MACHINE, L""));
+ SECURITY_CHECK(TestOpenKey(HKEY_CURRENT_USER, L""));
+ SECURITY_CHECK(TestOpenKey(HKEY_USERS, L""));
+ SECURITY_CHECK(TestOpenKey(HKEY_LOCAL_MACHINE,
+ L"Software\\Microsoft\\Windows NT\\CurrentVersion\\WinLogon"));
+ // Test below run on a separate thread because they cannot block the
+ // renderer process. Therefore they do not return a meaningful value.
+ PipeImpersonationAttack();
+ return TRUE;
+}
+
+// Runs the security tests of sandbox for the plugin process.
+// If a test fails, the return value is FALSE and test_count contains the
+// number of tests executed, including the failing test.
+BOOL __declspec(dllexport) __cdecl RunPluginTests(int *test_count) {
+ using namespace sandbox;
+ *test_count = 0;
+ SECURITY_CHECK(TestOpenWriteFile(L"%SystemRoot%"));
+ SECURITY_CHECK(TestOpenWriteFile(L"%ProgramFiles%"));
+ SECURITY_CHECK(TestOpenWriteFile(L"%SystemRoot%\\System32"));
+ SECURITY_CHECK(TestOpenWriteFile(L"%SystemRoot%\\explorer.exe"));
+ SECURITY_CHECK(TestOpenWriteFile(L"%SystemRoot%\\Cursors\\arrow_i.cur"));
+ return TRUE;
+}
diff --git a/chrome/test/security_tests/security_tests.vcproj b/chrome/test/security_tests/security_tests.vcproj
new file mode 100644
index 0000000..1149b68
--- /dev/null
+++ b/chrome/test/security_tests/security_tests.vcproj
@@ -0,0 +1,169 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="security_tests"
+ ProjectGUID="{E750512D-FC7C-4C98-BF04-0A0DAF882055}"
+ RootNamespace="security_tests"
+ Keyword="Win32Proj"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ ConfigurationType="2"
+ InheritedPropertySheets="$(SolutionDir)..\build\common.vsprops;$(SolutionDir)..\build\debug.vsprops"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ />
+ <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"
+ ConfigurationType="2"
+ InheritedPropertySheets="$(SolutionDir)..\build\common.vsprops;$(SolutionDir)..\build\release.vsprops"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ />
+ <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>
+ <File
+ RelativePath="..\..\..\sandbox\tests\validation_tests\commands.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\sandbox\tests\validation_tests\commands.h"
+ >
+ </File>
+ <File
+ RelativePath="..\injection_test_dll.h"
+ >
+ </File>
+ <File
+ RelativePath=".\ipc_security_tests.cc"
+ >
+ </File>
+ <File
+ RelativePath=".\ipc_security_tests.h"
+ >
+ </File>
+ <File
+ RelativePath=".\security_tests.cc"
+ >
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/chrome/test/selenium/README b/chrome/test/selenium/README
new file mode 100644
index 0000000..a9e60f6
--- /dev/null
+++ b/chrome/test/selenium/README
@@ -0,0 +1,2 @@
+This directory contains code to automate the selenium core test suite found
+under chrome/test/third_party/selenium_core/.
diff --git a/chrome/test/selenium/SConscript b/chrome/test/selenium/SConscript
new file mode 100644
index 0000000..eaa1b6e
--- /dev/null
+++ b/chrome/test/selenium/SConscript
@@ -0,0 +1,122 @@
+# 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.
+
+Import('env_test')
+
+env_test = env_test.Clone()
+
+env_test.Prepend(
+ CPPDEFINES = [
+ 'UI_TEST',
+ 'UNIT_TEST',
+ 'CERT_CHAIN_PARA_HAS_EXTRA_FIELDS',
+ 'WIN32_LEAN_AND_MEAN',
+ ],
+ CPPPATH = [
+ '$GTEST_DIR/include',
+ '$GTEST_DIR',
+ '$SKIA_DIR/include',
+ '$SKIA_DIR/include/corecg',
+ '$SKIA_DIR/platform',
+ '#/..',
+ ],
+ LINKFLAGS = [
+ '/INCREMENTAL',
+ '/DEBUG',
+
+ '/DELAYLOAD:"dwmapi.dll"',
+ '/DELAYLOAD:"uxtheme.dll"',
+
+ '/MACHINE:X86',
+ '/FIXED:No',
+
+ '/safeseh',
+ '/dynamicbase',
+ '/ignore:4199',
+ '/nxcompat',
+ ],
+ LIBS = [
+ 'winmm.lib',
+ 'rpcrt4.lib',
+ 'oleacc.lib',
+ 'comsupp.lib',
+
+ 'wininet.lib',
+ 'version.lib',
+ 'msimg32.lib',
+ 'ws2_32.lib',
+ 'usp10.lib',
+ 'psapi.lib',
+ 'kernel32.lib',
+ 'user32.lib',
+ 'gdi32.lib',
+ 'winspool.lib',
+ 'comdlg32.lib',
+ 'advapi32.lib',
+ 'shell32.lib',
+ 'ole32.lib',
+ 'oleaut32.lib',
+ 'uuid.lib',
+ 'odbc32.lib',
+ 'odbccp32.lib',
+
+ 'DelayImp.lib',
+ ],
+)
+
+input_files = [
+ '$CHROME_DIR/test/ui/run_all_unittests$OBJSUFFIX',
+ '$CHROME_DIR/test/ui/ui_test$OBJSUFFIX',
+ '$CHROME_DIR/test/ui/ui_test_suite$OBJSUFFIX',
+ '$CHROME_DIR/test/test_file_util$OBJSUFFIX',
+ 'selenium_test.cc',
+]
+
+libs = [
+ '$GOOGLEURL_DIR/googleurl.lib',
+ '$SKIA_DIR/skia.lib',
+ '$LIBPNG_DIR/libpng.lib',
+ '$TESTING_DIR/gtest.lib',
+ '$BASE_DIR/gfx/base_gfx.lib',
+ '$ICU38_DIR/icuuc.lib',
+ '$CHROME_DIR/common/common.lib',
+ '$ZLIB_DIR/zlib.lib',
+ '$MODP_B64_DIR/modp_b64.lib',
+ '$CHROME_DIR/browser/browser.lib',
+ '$NET_DIR/net.lib',
+ '$BASE_DIR/base.lib',
+ '$CHROME_DIR/test/automation/automation.lib',
+]
+
+exe = env_test.Program(['selenium_tests',
+ 'selenium_tests.pdb'],
+ input_files + libs)
+i = env_test.Install('$TARGET_ROOT', exe)
+
+env_test.Alias('chrome', i)
diff --git a/chrome/test/selenium/expected_failures.txt b/chrome/test/selenium/expected_failures.txt
new file mode 100644
index 0000000..455ac71
--- /dev/null
+++ b/chrome/test/selenium/expected_failures.txt
@@ -0,0 +1 @@
+46.type
diff --git a/chrome/test/selenium/selenium_test.cc b/chrome/test/selenium/selenium_test.cc
new file mode 100644
index 0000000..043def8
--- /dev/null
+++ b/chrome/test/selenium/selenium_test.cc
@@ -0,0 +1,196 @@
+// 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.
+
+// This is a gTest-based test that runs the Selenium Core testsuite in Chrome
+// using the UITest automation. The number of total and failed tests are
+// written to stdout.
+//
+// TODO(darin): output the names of the failed tests so we can easily track
+// deviations from the expected output.
+
+#include <list>
+#include <set>
+
+#include "base/file_util.h"
+#include "base/path_service.h"
+#include "base/string_util.h"
+#include "chrome/common/chrome_paths.h"
+#include "chrome/common/rand_util.h"
+#include "chrome/test/automation/tab_proxy.h"
+#include "chrome/test/automation/window_proxy.h"
+#include "chrome/test/ui/ui_test.h"
+#include "net/base/net_util.h"
+
+// Uncomment this to exercise this test without actually running the selenium
+// test, which can take a while to run. This define is useful when modifying
+// the analysis code.
+//#define SIMULATE_RUN 1
+
+namespace {
+
+// This file is a comma separated list of tests that are currently failing.
+const wchar_t kExpectedFailuresFileName[] = L"expected_failures.txt";
+
+class SeleniumTest : public UITest {
+ public:
+ SeleniumTest() {
+ show_window_ = true;
+ }
+ typedef std::list<std::string> ResultsList;
+ typedef std::set<std::string> ResultsSet;
+
+ // Parses a selenium results string, which is of the form:
+ // "5.selectFrame,6.click,24.selectAndWait,24.verifyTitle"
+ void ParseResults(const std::string& input, ResultsSet* output) {
+ if (input.empty())
+ return;
+
+ std::vector<std::string> tokens;
+ SplitString(input, ',', &tokens);
+ for (size_t i = 0; i < tokens.size(); ++i) {
+ TrimWhitespace(tokens[i], TRIM_ALL, &tokens[i]);
+ output->insert(tokens[i]);
+ }
+ }
+
+ // Find the elements of "b" that are not in "a"
+ void CompareSets(const ResultsSet& a, const ResultsSet& b,
+ ResultsList* only_in_b) {
+ ResultsSet::const_iterator it = b.begin();
+ for (; it != b.end(); ++it) {
+ if (a.find(*it) == a.end())
+ only_in_b->push_back(*it);
+ }
+ }
+
+ // The results file is in trunk/chrome/test/selenium/
+ std::wstring GetResultsFilePath() {
+ std::wstring results_path;
+ PathService::Get(chrome::DIR_TEST_DATA, &results_path);
+ file_util::UpOneDirectory(&results_path);
+ file_util::AppendToPath(&results_path, L"selenium");
+
+ file_util::AppendToPath(&results_path, kExpectedFailuresFileName);
+ return results_path;
+ }
+
+ bool ReadExpectedResults(std::string* results) {
+ std::wstring results_path = GetResultsFilePath();
+ return file_util::ReadFileToString(results_path, results);
+ }
+
+ void RunSelenium(std::wstring* total, std::wstring* failed) {
+#ifdef SIMULATE_RUN
+ *total = L"100";
+ const wchar_t* kBogusFailures[] = {
+ L"5.selectFrame,6.click,24.selectAndWait,24.verifyTitle",
+ L"5.selectFrame,6.click,13.verifyLocation,13.verifyLocation,13.click,24.selectAndWait,24.verifyTitle",
+ L"5.selectFrame,6.click,24.selectAndWait"
+ };
+ *failed = kBogusFailures[rand_util::RandInt(0, 2)];
+#else
+ std::wstring test_path;
+ PathService::Get(chrome::DIR_TEST_DATA, &test_path);
+ file_util::UpOneDirectory(&test_path);
+ file_util::UpOneDirectory(&test_path);
+ file_util::UpOneDirectory(&test_path);
+ file_util::AppendToPath(&test_path, L"data");
+ file_util::AppendToPath(&test_path, L"selenium_core");
+ file_util::AppendToPath(&test_path, L"core");
+ file_util::AppendToPath(&test_path, L"TestRunner.html");
+
+ GURL test_url(net_util::FilePathToFileURL(test_path));
+ scoped_ptr<TabProxy> tab(GetActiveTab());
+ tab->NavigateToURL(test_url);
+
+ // Wait for the test to finish.
+ ASSERT_TRUE(WaitUntilCookieValue(tab.get(), test_url, "__tests_finished",
+ 3000, UITest::test_timeout_ms(), "1"));
+
+ std::string cookie;
+ ASSERT_TRUE(tab->GetCookieByName(test_url, "__num_tests_total", &cookie));
+ total->swap(UTF8ToWide(cookie));
+ ASSERT_FALSE(total->empty());
+ ASSERT_TRUE(tab->GetCookieByName(test_url, "__tests_failed", &cookie));
+ failed->swap(UTF8ToWide(cookie));
+ // The __tests_failed cookie will be empty if all the tests pass.
+#endif
+ }
+
+ void RunTest(ResultsList* new_passes_list, ResultsList* new_failures_list) {
+ std::string expected_failures;
+ bool have_expected_results = ReadExpectedResults(&expected_failures);
+ ASSERT_TRUE(have_expected_results);
+
+ std::wstring total, failed;
+ RunSelenium(&total, &failed);
+ if (total.empty())
+ return;
+
+ printf("\n");
+ wprintf(L"__num_tests_total = [%s]\n", total.c_str());
+ wprintf(L"__tests_failed = [%s]\n", failed.c_str());
+
+ std::string cur_failures = WideToUTF8(failed);
+
+ ResultsSet expected_failures_set;
+ ParseResults(expected_failures, &expected_failures_set);
+
+ ResultsSet cur_failures_set;
+ ParseResults(cur_failures, &cur_failures_set);
+
+ // Compute the list of new passes and failures
+ CompareSets(cur_failures_set, expected_failures_set, new_passes_list);
+ CompareSets(expected_failures_set, cur_failures_set, new_failures_list);
+ }
+};
+
+} // namespace
+
+TEST_F(SeleniumTest, Core) {
+ ResultsList new_passes_list, new_failures_list;
+ RunTest(&new_passes_list, &new_failures_list);
+
+ if (!new_failures_list.empty()) {
+ ADD_FAILURE();
+ printf("new tests failing:\n");
+ ResultsList::const_iterator it = new_failures_list.begin();
+ for (; it != new_failures_list.end(); ++it)
+ printf(" %s\n", it->c_str());
+ printf("\n");
+ }
+
+ if (!new_passes_list.empty()) {
+ printf("new tests passing:\n");
+ ResultsList::const_iterator it = new_passes_list.begin();
+ for (; it != new_passes_list.end(); ++it)
+ printf(" %s\n", it->c_str());
+ printf("\n");
+ }
+}
diff --git a/chrome/test/selenium/selenium_tests.vcproj b/chrome/test/selenium/selenium_tests.vcproj
new file mode 100644
index 0000000..572819c
--- /dev/null
+++ b/chrome/test/selenium/selenium_tests.vcproj
@@ -0,0 +1,198 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="selenium_tests"
+ ProjectGUID="{E3749617-BA3D-4230-B54C-B758E56D9FA5}"
+ RootNamespace="selenium_tests"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ ConfigurationType="1"
+ InheritedPropertySheets="$(SolutionDir)..\build\common.vsprops;$(SolutionDir)..\build\debug.vsprops;..\..\tools\build\win\precompiled_wtl.vsprops;..\..\tools\build\win\unit_test.vsprops;..\..\tools\build\win\ui_test.vsprops;$(SolutionDir)..\skia\using_skia.vsprops;$(SolutionDir)..\testing\using_gtest.vsprops"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="winmm.lib"
+ />
+ <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"
+ ConfigurationType="1"
+ InheritedPropertySheets="$(SolutionDir)..\build\common.vsprops;$(SolutionDir)..\build\release.vsprops;..\..\tools\build\win\unit_test.vsprops;..\..\tools\build\win\ui_test.vsprops;$(SolutionDir)..\skia\using_skia.vsprops;$(SolutionDir)..\testing\using_gtest.vsprops"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="winmm.lib"
+ />
+ <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="Common"
+ >
+ <File
+ RelativePath="..\..\tools\build\win\precompiled_wtl.cc"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="1"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\tools\build\win\precompiled_wtl.h"
+ >
+ </File>
+ <File
+ RelativePath="..\ui\run_all_unittests.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\test_file_util.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\testing_browser_process.h"
+ >
+ </File>
+ <File
+ RelativePath="..\ui\ui_test.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\ui\ui_test.h"
+ >
+ </File>
+ <File
+ RelativePath="..\ui\ui_test_suite.cc"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="TestSelenium"
+ >
+ <File
+ RelativePath=".\selenium_test.cc"
+ >
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/chrome/test/startup/SConscript b/chrome/test/startup/SConscript
new file mode 100644
index 0000000..4f48ee5
--- /dev/null
+++ b/chrome/test/startup/SConscript
@@ -0,0 +1,121 @@
+# 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.
+
+Import('env_test')
+
+env_test = env_test.Clone()
+
+env_test.Prepend(
+ CPPDEFINES = [
+ 'UI_TEST',
+ 'UNIT_TEST',
+ 'CERT_CHAIN_PARA_HAS_EXTRA_FIELDS',
+ 'WIN32_LEAN_AND_MEAN',
+ ],
+ CPPPATH = [
+ '$GTEST_DIR/include',
+ '$GTEST_DIR',
+ '$SKIA_DIR/include',
+ '$SKIA_DIR/include/corecg',
+ '$SKIA_DIR/platform',
+ '#/..',
+ ],
+ LINKFLAGS = [
+ '/INCREMENTAL',
+ '/DEBUG',
+
+ '/DELAYLOAD:"dwmapi.dll"',
+ '/DELAYLOAD:"uxtheme.dll"',
+
+ '/MACHINE:X86',
+ '/FIXED:No',
+
+ '/safeseh',
+ '/dynamicbase',
+ '/ignore:4199',
+ '/nxcompat',
+ ],
+ LIBS = [
+ 'winmm.lib',
+ 'rpcrt4.lib',
+ 'oleacc.lib',
+ 'comsupp.lib',
+
+ 'wininet.lib',
+ 'version.lib',
+ 'msimg32.lib',
+ 'ws2_32.lib',
+ 'usp10.lib',
+ 'psapi.lib',
+ 'kernel32.lib',
+ 'user32.lib',
+ 'gdi32.lib',
+ 'winspool.lib',
+ 'comdlg32.lib',
+ 'advapi32.lib',
+ 'shell32.lib',
+ 'ole32.lib',
+ 'oleaut32.lib',
+ 'uuid.lib',
+ 'odbc32.lib',
+ 'odbccp32.lib',
+
+ 'DelayImp.lib',
+ ],
+)
+
+input_files = [
+ '$CHROME_DIR/test/ui/run_all_unittests$OBJSUFFIX',
+ '$CHROME_DIR/test/ui/ui_test$OBJSUFFIX',
+ '$CHROME_DIR/test/ui/ui_test_suite$OBJSUFFIX',
+ '$CHROME_DIR/test/test_file_util$OBJSUFFIX',
+ 'feature_startup_test.cc',
+ 'startup_test.cc',
+]
+
+libs = [
+ '$GOOGLEURL_DIR/googleurl.lib',
+ '$SKIA_DIR/skia.lib',
+ '$LIBPNG_DIR/libpng.lib',
+ '$TESTING_DIR/gtest.lib',
+ '$BASE_DIR/gfx/base_gfx.lib',
+ '$ICU38_DIR/icuuc.lib',
+ '$CHROME_DIR/common/common.lib',
+ '$ZLIB_DIR/zlib.lib',
+ '$CHROME_DIR/browser/browser.lib',
+ '$BASE_DIR/base.lib',
+ '$CHROME_DIR/test/automation/automation.lib',
+]
+
+exe = env_test.Program(['startup_tests',
+ 'startup_tests.pdb'],
+ input_files + libs)
+i = env_test.Install('$TARGET_ROOT', exe)
+
+env_test.Alias('chrome', i)
diff --git a/chrome/test/startup/feature_startup_test.cc b/chrome/test/startup/feature_startup_test.cc
new file mode 100644
index 0000000..3173fca
--- /dev/null
+++ b/chrome/test/startup/feature_startup_test.cc
@@ -0,0 +1,159 @@
+// 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.
+
+#include <windows.h>
+
+#include "base/file_util.h"
+#include "base/path_service.h"
+#include "base/perftimer.h"
+#include "base/time.h"
+#include "chrome/app/chrome_dll_resource.h"
+#include "chrome/common/chrome_paths.h"
+#include "chrome/common/win_util.h"
+#include "chrome/test/automation/browser_proxy.h"
+#include "chrome/test/ui/ui_test.h"
+#include "net/base/net_util.h"
+
+namespace {
+
+// Returns the directory name where the "typical" user data is that we use for
+// testing.
+std::wstring ComputeTypicalUserDataSource() {
+ std::wstring source_history_file;
+ EXPECT_TRUE(PathService::Get(chrome::DIR_TEST_DATA,
+ &source_history_file));
+ file_util::AppendToPath(&source_history_file, L"profiles");
+ file_util::AppendToPath(&source_history_file, L"typical_history");
+ return source_history_file;
+}
+
+class NewTabUIStartupTest : public UITest {
+ public:
+ NewTabUIStartupTest() {
+ show_window_ = true;
+ }
+
+ void SetUp() {}
+ void TearDown() {}
+
+ static const int kNumCycles = 5;
+
+ void PrintTimings(const char* label, TimeDelta timings[kNumCycles]) {
+ printf("\n%s = [", label);
+ for (int i = 0; i < kNumCycles; ++i) {
+ if (i > 0)
+ printf(",");
+ printf("%.2f", timings[i].InMillisecondsF());
+ }
+ printf("]\n");
+ }
+
+ // Run the test, by bringing up a browser and timing the new tab startup.
+ // |want_warm| is true if we should output warm-disk timings, false if
+ // we should report cold timings.
+ void RunStartupTest(bool want_warm) {
+ // Install the location of the test profile file.
+ set_template_user_data(ComputeTypicalUserDataSource());
+
+ TimeDelta timings[kNumCycles];
+ for (int i = 0; i < kNumCycles; ++i) {
+ UITest::SetUp();
+
+ // Switch to the "new tab" tab, which should be any new tab after the
+ // first (the first is about:blank).
+ BrowserProxy* window = automation()->GetBrowserWindow(0);
+ ASSERT_TRUE(window);
+ int old_tab_count = -1;
+ ASSERT_TRUE(window->GetTabCount(&old_tab_count));
+ ASSERT_EQ(1, old_tab_count);
+
+ // Hit ctl-t and wait for the tab to load.
+ window->ApplyAccelerator(IDC_NEWTAB);
+ int new_tab_count = -1;
+ ASSERT_TRUE(window->WaitForTabCountToChange(old_tab_count, &new_tab_count,
+ 5000));
+ ASSERT_EQ(2, new_tab_count);
+ int load_time;
+ ASSERT_TRUE(automation()->WaitForInitialNewTabUILoad(&load_time));
+ timings[i] = TimeDelta::FromMilliseconds(load_time);
+
+ if (want_warm) {
+ // Bring up a second tab, now that we've already shown one tab.
+ old_tab_count = new_tab_count;
+ new_tab_count = -1;
+ window->ApplyAccelerator(IDC_NEWTAB);
+ ASSERT_TRUE(window->WaitForTabCountToChange(old_tab_count, &new_tab_count,
+ 5000));
+ ASSERT_EQ(3, new_tab_count);
+ ASSERT_TRUE(automation()->WaitForInitialNewTabUILoad(&load_time));
+ timings[i] = TimeDelta::FromMilliseconds(load_time);
+ }
+
+ delete window;
+ UITest::TearDown();
+ }
+
+ // The buildbot log-scraper looks for this "__.._pages" line to tell when
+ // the test has completed and how many pages it loaded.
+ printf("\n__ts_pages = [about:blank]\n");
+ PrintTimings("__ts_timings", timings);
+ }
+};
+
+// The name of this test is important, since the buildbot runs with a gTest
+// filter.
+typedef NewTabUIStartupTest NewTabUIStartupTestReference;
+
+} // namespace
+
+TEST_F(NewTabUIStartupTest, PerfCold) {
+ RunStartupTest(false);
+}
+
+TEST_F(NewTabUIStartupTest, DISABLED_PerfWarm) {
+ RunStartupTest(true);
+}
+
+TEST_F(NewTabUIStartupTestReference, FakePerfForLogScraperCold) {
+ // Print an empty reference-test result line so the log-scraper is happy.
+ // TODO(pamg): really run the test with a reference build?
+ TimeDelta timings[kNumCycles];
+ for (int i = 0; i < kNumCycles; ++i)
+ timings[i] = TimeDelta::FromMilliseconds(0);
+ PrintTimings("__ts_reference_timings", timings);
+}
+
+TEST_F(NewTabUIStartupTestReference, FakePerfForLogScraperWarm) {
+ // Print an empty reference-test result line so the log-scraper is happy.
+ // TODO(pamg): really run the test with a reference build?
+ TimeDelta timings[kNumCycles];
+ for (int i = 0; i < kNumCycles; ++i)
+ timings[i] = TimeDelta::FromMilliseconds(0);
+ PrintTimings("__ts_reference_timings", timings);
+} \ No newline at end of file
diff --git a/chrome/test/startup/startup_test.cc b/chrome/test/startup/startup_test.cc
new file mode 100644
index 0000000..018faf8
--- /dev/null
+++ b/chrome/test/startup/startup_test.cc
@@ -0,0 +1,152 @@
+// 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.
+
+#include "base/file_util.h"
+#include "base/path_service.h"
+#include "base/time.h"
+#include "chrome/common/chrome_paths.h"
+#include "chrome/test/ui/ui_test.h"
+#include "net/base/net_util.h"
+
+namespace {
+
+class StartupTest : public UITest {
+ public:
+ StartupTest() {
+ show_window_ = true;
+ pages_ = "about:blank";
+ }
+ void SetUp() {}
+ void TearDown() {}
+
+ void RunStartupTest(const char* label, bool test_cold) {
+ const int kNumCycles = 20;
+
+ // Make a backup of gears.dll so we can overwrite the original, which
+ // flushes the disk cache for that file.
+ std::wstring chrome_dll, chrome_dll_copy;
+ ASSERT_TRUE(PathService::Get(chrome::DIR_APP, &chrome_dll));
+ file_util::AppendToPath(&chrome_dll, L"chrome.dll");
+ chrome_dll_copy = chrome_dll + L".copy";
+ ASSERT_TRUE(file_util::CopyFile(chrome_dll, chrome_dll_copy));
+
+ std::wstring gears_dll, gears_dll_copy;
+ ASSERT_TRUE(PathService::Get(chrome::FILE_GEARS_PLUGIN, &gears_dll));
+ gears_dll_copy = gears_dll + L".copy";
+ ASSERT_TRUE(file_util::CopyFile(gears_dll, gears_dll_copy));
+
+ TimeDelta timings[kNumCycles];
+ for (int i = 0; i < kNumCycles; ++i) {
+ if (test_cold) {
+ ASSERT_TRUE(file_util::CopyFile(chrome_dll_copy, chrome_dll));
+ ASSERT_TRUE(file_util::CopyFile(gears_dll_copy, gears_dll));
+ }
+
+ UITest::SetUp();
+ TimeTicks end_time = TimeTicks::Now();
+ timings[i] = end_time - browser_launch_time_;
+ // TODO(beng): Can't shut down so quickly. Figure out why, and fix. If we
+ // do, we crash.
+ Sleep(50);
+ UITest::TearDown();
+
+ if (i == 0) {
+ // Re-use the profile data after first run so that the noise from
+ // creating databases doesn't impact all the runs.
+ clear_profile_ = false;
+ }
+ }
+
+ ASSERT_TRUE(file_util::Delete(chrome_dll_copy, false));
+ ASSERT_TRUE(file_util::Delete(gears_dll_copy, false));
+
+ printf("\n__ts_pages = [%s]\n", pages_.c_str());
+ printf("\n%s = [", label);
+ for (int i = 0; i < kNumCycles; ++i) {
+ if (i > 0)
+ printf(",");
+ printf("%.2f", timings[i].InMillisecondsF());
+ }
+ printf("]\n");
+ }
+
+ protected:
+ std::string pages_;
+};
+
+class StartupReferenceTest : public StartupTest {
+ public:
+ // override the browser directory that is used by UITest::SetUp to cause it
+ // to use the reference build instead.
+ void SetUp() {
+ std::wstring dir;
+ PathService::Get(chrome::DIR_TEST_TOOLS, &dir);
+ file_util::AppendToPath(&dir, L"reference_build");
+ file_util::AppendToPath(&dir, L"chrome");
+ browser_directory_ = dir;
+ }
+};
+
+class StartupFileTest : public StartupTest {
+ public:
+ // Load a file on startup rather than about:blank. This tests a longer
+ // startup path, including resource loading and the loading of gears.dll.
+ void SetUp() {
+ std::wstring file_url;
+ ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &file_url));
+ file_util::AppendToPath(&file_url, L"empty.html");
+ ASSERT_TRUE(file_util::PathExists(file_url));
+ launch_arguments_ += file_url;
+
+ pages_ = WideToUTF8(file_url);
+ }
+};
+} // namespace
+
+TEST_F(StartupTest, Perf) {
+ RunStartupTest("__ts_timings", false);
+}
+
+TEST_F(StartupReferenceTest, Perf) {
+ RunStartupTest("__ts_reference_timings", false);
+}
+
+// TODO(mpcomplete): Should we have reference timings for all these?
+
+TEST_F(StartupTest, PerfCold) {
+ RunStartupTest("__ts_cold_timings", true);
+}
+
+TEST_F(StartupFileTest, PerfGears) {
+ RunStartupTest("__ts_gears_timings", false);
+}
+
+TEST_F(StartupFileTest, PerfColdGears) {
+ RunStartupTest("__ts_cold_gears_timings", true);
+}
diff --git a/chrome/test/startup/startup_tests.vcproj b/chrome/test/startup/startup_tests.vcproj
new file mode 100644
index 0000000..e7f38a2
--- /dev/null
+++ b/chrome/test/startup/startup_tests.vcproj
@@ -0,0 +1,206 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="startup_tests"
+ ProjectGUID="{D3E6C0FD-54C7-4FF2-9AE1-72F2DAFD820C}"
+ RootNamespace="startup_tests"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ ConfigurationType="1"
+ InheritedPropertySheets="$(SolutionDir)..\build\common.vsprops;$(SolutionDir)..\build\debug.vsprops;..\..\tools\build\win\precompiled.vsprops;..\..\tools\build\win\unit_test.vsprops;..\..\tools\build\win\ui_test.vsprops;$(SolutionDir)..\skia\using_skia.vsprops;$(SolutionDir)..\testing\using_gtest.vsprops"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="winmm.lib"
+ />
+ <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"
+ ConfigurationType="1"
+ InheritedPropertySheets="$(SolutionDir)..\build\common.vsprops;$(SolutionDir)..\build\release.vsprops;..\..\tools\build\win\unit_test.vsprops;..\..\tools\build\win\ui_test.vsprops;$(SolutionDir)..\skia\using_skia.vsprops;$(SolutionDir)..\testing\using_gtest.vsprops"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="winmm.lib"
+ />
+ <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="Common"
+ >
+ <File
+ RelativePath="..\..\tools\build\win\precompiled.cc"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="1"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\tools\build\win\precompiled.h"
+ >
+ </File>
+ <File
+ RelativePath="..\ui\run_all_unittests.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\test_file_util.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\test_file_util.h"
+ >
+ </File>
+ <File
+ RelativePath="..\testing_browser_process.h"
+ >
+ </File>
+ <File
+ RelativePath="..\ui\ui_test.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\ui\ui_test.h"
+ >
+ </File>
+ <File
+ RelativePath="..\ui\ui_test_suite.cc"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="TestStartup"
+ >
+ <File
+ RelativePath=".\feature_startup_test.cc"
+ >
+ </File>
+ <File
+ RelativePath=".\startup_test.cc"
+ >
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/chrome/test/tab_switching/SConscript b/chrome/test/tab_switching/SConscript
new file mode 100644
index 0000000..d825fa3
--- /dev/null
+++ b/chrome/test/tab_switching/SConscript
@@ -0,0 +1,125 @@
+# 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.
+
+Import('env_test')
+
+env_test = env_test.Clone()
+
+env_test.Prepend(
+ CPPDEFINES = [
+ 'UI_TEST',
+ 'UNIT_TEST',
+ 'CERT_CHAIN_PARA_HAS_EXTRA_FIELDS',
+ 'WIN32_LEAN_AND_MEAN',
+ ],
+ CPPPATH = [
+ '$GTEST_DIR/include',
+ '$GTEST_DIR',
+ '$SKIA_DIR/include',
+ '$SKIA_DIR/include/corecg',
+ '$SKIA_DIR/platform',
+ '#/..',
+ ],
+ LINKFLAGS = [
+ '/INCREMENTAL',
+ '/DEBUG',
+
+ '/DELAYLOAD:"dwmapi.dll"',
+ '/DELAYLOAD:"uxtheme.dll"',
+
+ '/MACHINE:X86',
+ '/FIXED:No',
+
+ '/safeseh',
+ '/dynamicbase',
+ '/ignore:4199',
+ '/nxcompat',
+ ],
+ LIBS = [
+ 'winmm.lib',
+ 'psapi.lib',
+ 'rpcrt4.lib',
+ 'oleacc.lib',
+ 'comsupp.lib',
+
+ 'wininet.lib',
+ 'version.lib',
+ 'msimg32.lib',
+ 'ws2_32.lib',
+ 'usp10.lib',
+ 'psapi.lib',
+ 'kernel32.lib',
+ 'user32.lib',
+ 'gdi32.lib',
+ 'winspool.lib',
+ 'comdlg32.lib',
+ 'advapi32.lib',
+ 'shell32.lib',
+ 'ole32.lib',
+ 'oleaut32.lib',
+ 'uuid.lib',
+ 'odbc32.lib',
+ 'odbccp32.lib',
+
+ 'DelayImp.lib',
+ ],
+)
+
+input_files = [
+ '$CHROME_DIR/test/ui/run_all_unittests$OBJSUFFIX',
+ '$CHROME_DIR/test/ui/ui_test$OBJSUFFIX',
+ '$CHROME_DIR/test/ui/ui_test_suite$OBJSUFFIX',
+ '$CHROME_DIR/test/test_file_util$OBJSUFFIX',
+ 'tab_switching_test.cc',
+]
+
+libs = [
+ '$GOOGLEURL_DIR/googleurl.lib',
+ '$SKIA_DIR/skia.lib',
+ '$LIBPNG_DIR/libpng.lib',
+ '$TESTING_DIR/gtest.lib',
+ '$BASE_DIR/gfx/base_gfx.lib',
+ '$ICU38_DIR/icuuc.lib',
+ '$CHROME_DIR/common/common.lib',
+ '$ZLIB_DIR/zlib.lib',
+ '$MODP_B64_DIR/modp_b64.lib',
+ '$CHROME_DIR/browser/browser.lib',
+ '$NET_DIR/net.lib',
+ '$BASE_DIR/base.lib',
+ '$CHROME_DIR/test/automation/automation.lib',
+]
+
+#"..\..\Debug\obj\tab_switching_test\precompiled_wtl.obj"
+
+exe = env_test.Program(['tab_switching_test',
+ 'tab_switching_test.pdb'],
+ input_files + libs)
+i = env_test.Install('$TARGET_ROOT', exe)
+
+env_test.Alias('chrome', i)
diff --git a/chrome/test/tab_switching/tab_switching.vcproj b/chrome/test/tab_switching/tab_switching.vcproj
new file mode 100644
index 0000000..d9a9b03
--- /dev/null
+++ b/chrome/test/tab_switching/tab_switching.vcproj
@@ -0,0 +1,198 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="tab_switching_test"
+ ProjectGUID="{A34770EA-A574-43E8-9327-F79C04770E98}"
+ RootNamespace="tab_switching_test"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ ConfigurationType="1"
+ InheritedPropertySheets="$(SolutionDir)..\build\common.vsprops;$(SolutionDir)..\build\debug.vsprops;..\..\tools\build\win\precompiled_wtl.vsprops;..\..\tools\build\win\unit_test.vsprops;..\..\tools\build\win\ui_test.vsprops;..\..\tools\build\win\test_memory_usage.vsprops;$(SolutionDir)..\skia\using_skia.vsprops;$(SolutionDir)..\testing\using_gtest.vsprops"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="winmm.lib"
+ />
+ <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"
+ ConfigurationType="1"
+ InheritedPropertySheets="$(SolutionDir)..\build\common.vsprops;$(SolutionDir)..\build\release.vsprops;..\..\tools\build\win\unit_test.vsprops;..\..\tools\build\win\ui_test.vsprops;..\..\tools\build\win\test_memory_usage.vsprops;$(SolutionDir)..\skia\using_skia.vsprops;$(SolutionDir)..\testing\using_gtest.vsprops"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="winmm.lib"
+ />
+ <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="Common"
+ >
+ <File
+ RelativePath="..\..\tools\build\win\precompiled_wtl.cc"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="1"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\tools\build\win\precompiled_wtl.h"
+ >
+ </File>
+ <File
+ RelativePath="..\ui\run_all_unittests.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\test_file_util.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\testing_browser_process.h"
+ >
+ </File>
+ <File
+ RelativePath="..\ui\ui_test.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\ui\ui_test.h"
+ >
+ </File>
+ <File
+ RelativePath="..\ui\ui_test_suite.cc"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="TabSwitchingTest"
+ >
+ <File
+ RelativePath=".\tab_switching_test.cc"
+ >
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/chrome/test/tab_switching/tab_switching_test.cc b/chrome/test/tab_switching/tab_switching_test.cc
new file mode 100644
index 0000000..2b96bc8
--- /dev/null
+++ b/chrome/test/tab_switching/tab_switching_test.cc
@@ -0,0 +1,170 @@
+// 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.
+
+#include "base/command_line.h"
+#include "base/file_util.h"
+#include "base/time.h"
+#include "chrome/app/chrome_dll_resource.h"
+#include "chrome/common/chrome_paths.h"
+#include "chrome/common/chrome_switches.h"
+#include "chrome/common/pref_names.h"
+#include "chrome/test/automation/tab_proxy.h"
+#include "chrome/test/automation/browser_proxy.h"
+#include "chrome/test/ui/ui_test.h"
+#include "googleurl/src/gurl.h"
+#include "net/base/net_util.h"
+
+#define NUMBER_OF_ITERATIONS 5
+
+namespace {
+
+// This Automated UI test opens static files in different tabs in a proxy
+// browser. After all the tabs have opened, it switches between tabs, and notes
+// time taken for each switch. It then prints out the times on the console,
+// with the aim that the page cycler parser can interpret these numbers to
+// draw graphs for page cycler Tab Switching Performance.
+// Usage Flags: -enable-logging -dump-histograms-on-exit
+class TabSwitchingUITest : public UITest {
+ public:
+ TabSwitchingUITest() {
+ PathService::Get(base::DIR_EXE, &path_prefix_);
+ file_util::UpOneDirectory(&path_prefix_);
+ file_util::UpOneDirectory(&path_prefix_);
+ file_util::AppendToPath(&path_prefix_, L"data");
+ file_util::AppendToPath(&path_prefix_, L"tab_switching");
+ path_prefix_ += file_util::kPathSeparator;
+
+ show_window_ = true;
+ }
+
+ void RunTabSwitchingUITest() {
+ // Create a browser proxy.
+ browser_proxy_.reset(automation()->GetBrowserWindow(0));
+
+ // Open all the tabs.
+ int initial_tab_count = 0;
+ ASSERT_TRUE(browser_proxy_->GetTabCount(&initial_tab_count));
+ int new_tab_count = OpenTabs();
+ int final_tab_count = 0;
+ ASSERT_TRUE(browser_proxy_->WaitForTabCountToChange(initial_tab_count,
+ &final_tab_count,
+ 10000));
+ ASSERT_TRUE(final_tab_count == initial_tab_count + new_tab_count);
+
+ // Switch linearly between tabs.
+ browser_proxy_->ActivateTab(0);
+ for (int i = initial_tab_count; i < final_tab_count; ++i) {
+ browser_proxy_->ActivateTab(i);
+ ASSERT_TRUE(browser_proxy_->WaitForTabToBecomeActive(i, 10000));
+ }
+
+ // Close the browser to force a dump of log.
+ bool application_closed = false;
+ EXPECT_TRUE(CloseBrowser(browser_proxy_.get(), &application_closed));
+
+ // Now open the corresponding log file and collect average and std dev from
+ // the histogram stats generated for RenderWidgetHostHWND_WhiteoutDuration
+ std::wstring log_file_name;
+ PathService::Get(chrome::DIR_LOGS, &log_file_name);
+ file_util::AppendToPath(&log_file_name, L"chrome_debug.log");
+
+ bool log_has_been_dumped = false;
+ std::string contents;
+ do {
+ log_has_been_dumped = file_util::ReadFileToString(log_file_name,
+ &contents);
+ } while (!log_has_been_dumped);
+
+ // Parse the contents to get average and std deviation.
+ std::string average("0.0"), std_dev("0.0");
+ const std::string average_str("average = ");
+ const std::string std_dev_str("standard deviation = ");
+ std::string::size_type pos = contents.find(
+ "Histogram: RenderWidgetHostHWND_WhiteoutDuration", 0);
+ std::string::size_type comma_pos;
+ std::string::size_type number_length;
+ if (pos != std::string::npos) {
+ // Get the average.
+ pos = contents.find(average_str, pos);
+ comma_pos = contents.find(",", pos);
+ pos += average_str.length();
+ number_length = comma_pos - pos;
+ average = contents.substr(pos, number_length);
+
+ // Get the std dev.
+ pos = contents.find(std_dev_str, pos);
+ pos += std_dev_str.length();
+ comma_pos = contents.find(" ", pos);
+ number_length = comma_pos - pos;
+ std_dev = contents.substr(pos, number_length);
+ }
+
+ // Print the average and standard deviation.
+ // Format: __tsw_timings = [512.00, 419.17]
+ // Where 512.00 = average
+ // 419.17 = std dev.
+ printf("__tsw_timings = [%s,%s]\n", average.c_str(), std_dev.c_str());
+ }
+
+ protected:
+ // Opens new tabs. Returns the number of tabs opened.
+ int OpenTabs() {
+ // Add tabs.
+ static const wchar_t* files[] = { L"espn.go.com", L"bugzilla.mozilla.org",
+ L"news.cnet.com", L"www.amazon.com",
+ L"kannada.chakradeo.net", L"allegro.pl",
+ L"ml.wikipedia.org", L"www.bbc.co.uk",
+ L"126.com", L"www.altavista.com"};
+ int number_of_new_tabs_opened = 0;
+ std::wstring file_name;
+ for (int i = 0; i < arraysize(files); ++i) {
+ file_name = path_prefix_;
+ file_name += files[i];
+ file_name += file_util::kPathSeparator;
+ file_name += L"index.html";
+ browser_proxy_->AppendTab(net_util::FilePathToFileURL(file_name));
+ number_of_new_tabs_opened++;
+ }
+
+ return number_of_new_tabs_opened;
+ }
+
+ std::wstring path_prefix_;
+ int number_of_tabs_to_open_;
+ scoped_ptr<BrowserProxy> browser_proxy_;
+
+ private:
+ DISALLOW_EVIL_CONSTRUCTORS(TabSwitchingUITest);
+};
+
+} // namespace
+
+TEST_F(TabSwitchingUITest, GenerateTabSwitchStats) {
+ RunTabSwitchingUITest();
+}
diff --git a/chrome/test/test_file_util.cc b/chrome/test/test_file_util.cc
new file mode 100644
index 0000000..55917f2
--- /dev/null
+++ b/chrome/test/test_file_util.cc
@@ -0,0 +1,124 @@
+// 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.
+
+#include <vector>
+#include <windows.h>
+
+#include "chrome/test/test_file_util.h"
+
+#include "base/file_util.h"
+#include "chrome/common/win_util.h"
+
+namespace file_util {
+
+bool EvictFileFromSystemCache(const wchar_t* file) {
+ // Request exclusive access to the file and overwrite it with no buffering.
+ win_util::ScopedHandle hfile(
+ CreateFile(file, GENERIC_READ | GENERIC_WRITE, 0, NULL,
+ OPEN_EXISTING, FILE_FLAG_NO_BUFFERING,
+ NULL));
+ if (!hfile)
+ return false;
+
+ // Execute in chunks. It could be optimized. We want to do few of these since
+ // these opterations will be slow without the cache.
+ char buffer[4096];
+ int total_bytes = 0;
+ DWORD bytes_read;
+ for (;;) {
+ bytes_read = 0;
+ ReadFile(hfile, buffer, sizeof(buffer), &bytes_read, NULL);
+ if (bytes_read == 0)
+ break;
+
+ SetFilePointer(hfile, total_bytes, 0, FILE_BEGIN);
+ if (!WriteFile(hfile, buffer, bytes_read, &bytes_read, NULL))
+ return false;
+ total_bytes += bytes_read;
+ }
+ return true;
+}
+
+// Like CopyFileNoCache but recursively copies all files and subdirectories
+// in the given input directory to the output directory.
+bool CopyRecursiveDirNoCache(const std::wstring& source_dir,
+ const std::wstring& dest_dir) {
+ // Try to create the directory if it doesn't already exist.
+ if (!CreateDirectory(dest_dir)) {
+ if (GetLastError() != ERROR_ALREADY_EXISTS)
+ return false;
+ }
+
+ std::vector<std::wstring> files_copied;
+
+ std::wstring src(source_dir);
+ file_util::AppendToPath(&src, L"*");
+
+ WIN32_FIND_DATA fd;
+ HANDLE fh = FindFirstFile(src.c_str(), &fd);
+ if (fh == INVALID_HANDLE_VALUE)
+ return false;
+
+ do {
+ std::wstring cur_file(fd.cFileName);
+ if (cur_file == L"." || cur_file == L"..")
+ continue; // Skip these special entries.
+
+ std::wstring cur_source_path(source_dir);
+ file_util::AppendToPath(&cur_source_path, cur_file);
+
+ std::wstring cur_dest_path(dest_dir);
+ file_util::AppendToPath(&cur_dest_path, cur_file);
+
+ if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
+ // Recursively copy a subdirectory. We stripped "." and ".." already.
+ if (!CopyRecursiveDirNoCache(cur_source_path, cur_dest_path)) {
+ FindClose(fh);
+ return false;
+ }
+ } else {
+ // Copy the file.
+ if (!::CopyFile(cur_source_path.c_str(), cur_dest_path.c_str(), false)) {
+ FindClose(fh);
+ return false;
+ }
+
+ // We don't check for errors from this function, often, we are copying
+ // files that are in the repository, and they will have read-only set.
+ // This will prevent us from evicting from the cache, but these don't
+ // matter anyway.
+ EvictFileFromSystemCache(cur_dest_path.c_str());
+ }
+ } while (FindNextFile(fh, &fd));
+
+ FindClose(fh);
+ return true;
+}
+
+} // namespace file_util
diff --git a/chrome/test/test_file_util.h b/chrome/test/test_file_util.h
new file mode 100644
index 0000000..dcc7c22
--- /dev/null
+++ b/chrome/test/test_file_util.h
@@ -0,0 +1,55 @@
+// 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.
+
+#ifndef CHROME_TEST_TEST_FILE_UTIL_H__
+#define CHROME_TEST_TEST_FILE_UTIL_H__
+
+// File utility functions used only by tests.
+
+#include <string>
+
+namespace file_util {
+
+// Clear a specific file from the system cache using a neat trick. After this
+// call, trying to access this file will result in a cold load from the hard
+// drive.
+bool EvictFileFromSystemCache(const wchar_t* file);
+
+// Like CopyFileNoCache but recursively copies all files and subdirectories
+// in the given input directory to the output directory. Any files in the
+// destination that already exist will be overwritten.
+//
+// Returns true on success. False means there was some error copying, so the
+// state of the destination is unknown.
+bool CopyRecursiveDirNoCache(const std::wstring& source_dir,
+ const std::wstring& dest_dir);
+
+} // namespace file_util
+
+#endif // CHROME_TEST_TEST_FILE_UTIL_H__
diff --git a/chrome/test/testing_browser_process.h b/chrome/test/testing_browser_process.h
new file mode 100644
index 0000000..2ccd7e0
--- /dev/null
+++ b/chrome/test/testing_browser_process.h
@@ -0,0 +1,151 @@
+// 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.
+
+// An implementation of BrowserProcess for unit tests that fails for most
+// services. By preventing creation of services, we reduce dependencies and
+// keep the profile clean. Clients of this class must handle the NULL return
+// value, however.
+
+#ifndef CHROME_TEST_TESTING_BROWSER_PROCESS_H__
+#define CHROME_TEST_TESTING_BROWSER_PROCESS_H__
+
+#include <string>
+
+#include "base/string_util.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/common/notification_service.h"
+#include "base/logging.h"
+
+class TestingBrowserProcess : public BrowserProcess {
+ public:
+ TestingBrowserProcess() {}
+ virtual ~TestingBrowserProcess() {
+ }
+
+ virtual void EndSession() {
+ }
+
+ virtual ResourceDispatcherHost* resource_dispatcher_host() {
+ return NULL;
+ }
+
+ virtual MetricsService* metrics_service() {
+ return NULL;
+ }
+
+ virtual Thread* io_thread() {
+ return NULL;
+ }
+
+ virtual Thread* file_thread() {
+ return NULL;
+ }
+
+ virtual Thread* db_thread() {
+ return NULL;
+ }
+
+ virtual ProfileManager* profile_manager() {
+ return NULL;
+ }
+
+ virtual PrefService* local_state() {
+ return NULL;
+ }
+
+ virtual WebAppInstallerService* web_app_installer_service() {
+ return NULL;
+ }
+
+ virtual IconManager* icon_manager() {
+ return NULL;
+ }
+
+ virtual sandbox::BrokerServices* broker_services() {
+ return NULL;
+ }
+
+ virtual DebuggerWrapper* debugger_wrapper() {
+ return NULL;
+ }
+
+ virtual ClipboardService* clipboard_service() {
+ return NULL;
+ }
+
+ virtual GoogleURLTracker* google_url_tracker() {
+ return NULL;
+ }
+
+ virtual void InitBrokerServices(sandbox::BrokerServices*) {
+ }
+
+ virtual AutomationProviderList* InitAutomationProviderList() {
+ return NULL;
+ }
+
+ virtual void InitDebuggerWrapper(int port) {
+ }
+
+ virtual unsigned int AddRefModule() {
+ return 1;
+ }
+ virtual unsigned int ReleaseModule() {
+ return 1;
+ }
+
+ virtual bool IsShuttingDown() {
+ return false;
+ }
+
+ virtual ChromeViews::AcceleratorHandler* accelerator_handler() {
+ return NULL;
+ }
+
+ virtual printing::PrintJobManager* print_job_manager() {
+ return NULL;
+ }
+
+ virtual const std::wstring& GetApplicationLocale() {
+ static std::wstring* value = NULL;
+ if (!value)
+ value = new std::wstring(L"en");
+ return *value;
+ }
+
+ virtual MemoryModel memory_model() { return HIGH_MEMORY_MODEL; }
+
+ virtual SuspendController* suspend_controller() { return NULL; }
+
+ private:
+ NotificationService notification_service_;
+ DISALLOW_EVIL_CONSTRUCTORS(TestingBrowserProcess);
+};
+
+#endif // CHROME_TEST_TESTING_BROWSER_PROCESS_H__
diff --git a/chrome/test/testing_profile.cc b/chrome/test/testing_profile.cc
new file mode 100644
index 0000000..ac9e9f7
--- /dev/null
+++ b/chrome/test/testing_profile.cc
@@ -0,0 +1,69 @@
+// 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.
+
+#include "chrome/test/testing_profile.h"
+
+TestingProfile::~TestingProfile() {
+ DestroyHistoryService();
+}
+
+void TestingProfile::CreateHistoryService() {
+ DCHECK(!history_service_.get());
+
+ PathService::Get(base::DIR_TEMP, &history_dir_);
+ file_util::AppendToPath(&history_dir_, L"HistoryTest");
+ file_util::Delete(history_dir_, true);
+ file_util::CreateDirectory(history_dir_);
+ history_service_ = new HistoryService();
+ history_service_->Init(history_dir_);
+}
+
+void TestingProfile::DestroyHistoryService() {
+ if (!history_service_.get())
+ return;
+
+ history_service_->NotifyRenderProcessHostDestruction(0);
+ history_service_->SetOnBackendDestroyTask(new MessageLoop::QuitTask);
+ history_service_->Cleanup();
+ history_service_ = NULL;
+
+ // Wait for the backend class to terminate before deleting the files and
+ // moving to the next test. Note: if this never terminates, somebody is
+ // probably leaking a reference to the history backend, so it never calls
+ // our destroy task.
+ MessageLoop::current()->Run();
+
+ // Try to clean up the database file.
+ file_util::Delete(history_dir_, true);
+
+ // Make sure we don't have any event pending that could disrupt the next
+ // test.
+ MessageLoop::current()->PostTask(FROM_HERE, new MessageLoop::QuitTask);
+ MessageLoop::current()->Run();
+}
diff --git a/chrome/test/testing_profile.h b/chrome/test/testing_profile.h
new file mode 100644
index 0000000..ae6c356
--- /dev/null
+++ b/chrome/test/testing_profile.h
@@ -0,0 +1,176 @@
+// 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.
+
+#ifndef CHROME_TEST_TESTING_PROFILE_H__
+#define CHROME_TEST_TESTING_PROFILE_H__
+
+#include "base/base_paths.h"
+#include "base/path_service.h"
+#include "base/file_util.h"
+#include "chrome/browser/browser_prefs.h"
+#include "chrome/browser/history/history.h"
+#include "chrome/browser/profile.h"
+#include "chrome/common/pref_service.h"
+
+class TestingProfile : public Profile {
+ public:
+ TestingProfile() : start_time_(Time::Now()) {}
+ virtual ~TestingProfile();
+
+ // Creates the HistoryService. Normally there is no HistoryService.
+ void CreateHistoryService();
+
+ virtual std::wstring GetPath() {
+ return std::wstring();
+ }
+ virtual bool IsOffTheRecord() {
+ return false;
+ }
+ virtual Profile* GetOffTheRecordProfile() {
+ return NULL;
+ }
+ virtual Profile* GetOriginalProfile() {
+ return this;
+ }
+ virtual VisitedLinkMaster* GetVisitedLinkMaster() {
+ return NULL;
+ }
+ virtual HistoryService* GetHistoryService(ServiceAccessType access) {
+ return history_service_.get();
+ }
+ virtual bool HasHistoryService() const {
+ return (history_service_.get() != NULL);
+ }
+ virtual WebDataService* GetWebDataService(ServiceAccessType access) {
+ return NULL;
+ }
+ virtual PrefService* GetPrefs() {
+ std::wstring prefs_filename;
+ PathService::Get(base::DIR_TEMP, &prefs_filename);
+ file_util::AppendToPath(&prefs_filename, L"TestPreferences");
+ if (!prefs_.get()) {
+ prefs_.reset(new PrefService(prefs_filename));
+ Profile::RegisterUserPrefs(prefs_.get());
+ browser::RegisterAllPrefs(prefs_.get(), prefs_.get());
+ }
+ return prefs_.get();
+ }
+ virtual TemplateURLModel* GetTemplateURLModel() {
+ return NULL;
+ }
+ virtual TemplateURLFetcher* GetTemplateURLFetcher() {
+ return NULL;
+ }
+ virtual DownloadManager* GetDownloadManager() {
+ return NULL;
+ }
+ virtual bool HasCreatedDownloadManager() const {
+ return false;
+ }
+ virtual URLRequestContext* GetRequestContext() {
+ return NULL;
+ }
+ virtual SessionService* GetSessionService() {
+ return NULL;
+ }
+ virtual void ShutdownSessionService() {
+ }
+ virtual bool HasSessionService() const {
+ return false;
+ }
+ virtual std::wstring GetName() {
+ return std::wstring();
+ }
+ virtual void SetName(const std::wstring& name) {
+ }
+ virtual std::wstring GetID() {
+ return std::wstring();
+ }
+ virtual void SetID(const std::wstring& id) {
+ }
+ virtual void RegisterNavigationController(
+ NavigationController* controller) {
+ }
+ virtual void UnregisterNavigationController(
+ NavigationController* controller) {
+ }
+ virtual const ProfileControllerSet& GetNavigationControllers() {
+ return controllers_;
+ }
+ virtual bool DidLastSessionExitCleanly() {
+ return true;
+ }
+ virtual void MergeResourceString(int message_id,
+ std::wstring* output_string) {
+ }
+ virtual void MergeResourceInteger(int message_id, int* output_value) {
+ }
+ virtual void MergeResourceBoolean(int message_id, bool* output_value) {
+ }
+ virtual bool HasBookmarkBarModel() {
+ return false;
+ }
+ virtual BookmarkBarModel* GetBookmarkBarModel() {
+ return NULL;
+ }
+ virtual bool Profile::IsSameProfile(Profile *p) {
+ return this == p;
+ }
+ virtual Time GetStartTime() const {
+ return start_time_;
+ }
+ virtual TabRestoreService* GetTabRestoreService() {
+ return NULL;
+ }
+ virtual void ResetTabRestoreService() {
+ }
+ virtual SpellChecker* GetSpellChecker() {
+ return NULL;
+ }
+ virtual void MarkAsCleanShutdown() {
+ }
+
+ protected:
+ Time start_time_;
+ ProfileControllerSet controllers_;
+ scoped_ptr<PrefService> prefs_;
+
+ private:
+ // If the history service has been created, it is destroyed. This is invoked
+ // from the destructor.
+ void DestroyHistoryService();
+
+ // Directory for the history service.
+ std::wstring history_dir_;
+
+ // The history service. Only created if CreateHistoryService is invoked.
+ scoped_refptr<HistoryService> history_service_;
+};
+
+#endif // CHROME_TEST_TESTING_PROFILE_H__
diff --git a/chrome/test/ui/inspector_controller_uitest.cc b/chrome/test/ui/inspector_controller_uitest.cc
new file mode 100644
index 0000000..6ca6a91
--- /dev/null
+++ b/chrome/test/ui/inspector_controller_uitest.cc
@@ -0,0 +1,73 @@
+// 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.
+
+#include "base/command_line.h"
+#include "base/no_windows2000_unittest.h"
+#include "base/win_util.h"
+#include "chrome/common/chrome_switches.h"
+#include "chrome/test/automation/browser_proxy.h"
+#include "chrome/test/automation/tab_proxy.h"
+#include "chrome/test/ui/ui_test.h"
+#include "net/url_request/url_request_unittest.h"
+
+// This test does not work on win2k. See http://b/1070036
+class InspectorControllerTest : public NoWindows2000Test<UITest> {
+ protected:
+ TabProxy* GetActiveTabProxy() {
+ scoped_ptr<BrowserProxy> window_proxy(automation()->GetBrowserWindow(0));
+ EXPECT_TRUE(window_proxy.get());
+
+ int active_tab_index = 0;
+ EXPECT_TRUE(window_proxy->GetActiveTabIndex(&active_tab_index));
+ return window_proxy->GetTab(active_tab_index);
+ }
+
+ void NavigateTab(TabProxy* tab_proxy, const GURL& url) {
+ ASSERT_TRUE(tab_proxy->NavigateToURL(url));
+ }
+};
+
+// This test also does not work in single process. See http://b/1214920
+TEST_F(InspectorControllerTest, InspectElement) {
+ if (IsTestCaseDisabled())
+ return;
+
+ if (CommandLine().HasSwitch(switches::kSingleProcess))
+ return;
+
+ TestServer server(L"chrome/test/data");
+ ::scoped_ptr<TabProxy> tab(GetActiveTabProxy());
+ // We don't track resources until we've opened the inspector.
+ NavigateTab(tab.get(), server.TestServerPageW(L"files/inspector/test1.html"));
+ tab->InspectElement(0, 0);
+ NavigateTab(tab.get(), server.TestServerPageW(L"files/inspector/test1.html"));
+ EXPECT_EQ(1, tab->InspectElement(0, 0));
+ NavigateTab(tab.get(), server.TestServerPageW(L"files/inspector/test2.html"));
+ EXPECT_EQ(2, tab->InspectElement(0, 0));
+}
diff --git a/chrome/test/ui/layout_plugin_uitest.cpp b/chrome/test/ui/layout_plugin_uitest.cpp
new file mode 100644
index 0000000..1a3e973
--- /dev/null
+++ b/chrome/test/ui/layout_plugin_uitest.cpp
@@ -0,0 +1,73 @@
+// 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.
+
+#include "chrome/test/ui/ui_test.h"
+
+#include "base/file_util.h"
+#include "chrome/common/chrome_paths.h"
+#include "chrome/test/automation/tab_proxy.h"
+#include "googleurl/src/gurl.h"
+#include "net/base/net_util.h"
+
+namespace {
+
+class LayoutPluginTester : public UITest {
+};
+
+} // namespace
+
+// Make sure that navigating away from a plugin referenced by JS doesn't
+// crash.
+TEST_F(LayoutPluginTester, UnloadNoCrash) {
+ // We need to copy our test-plugin into the plugins directory so that
+ // the browser can load it.
+ std::wstring plugins_directory = browser_directory_ + L"\\plugins";
+ std::wstring plugin_src = browser_directory_ + L"\\npapi_layout_test_plugin.dll";
+ std::wstring plugin_dest = plugins_directory + L"\\npapi_layout_test_plugin.dll";
+
+ CreateDirectory(plugins_directory.c_str(), NULL);
+ CopyFile(plugin_src.c_str(), plugin_dest.c_str(), true /* overwrite */);
+
+ std::wstring path;
+ PathService::Get(chrome::DIR_TEST_DATA, &path);
+ file_util::AppendToPath(&path, L"npapi/layout_test_plugin.html");
+ NavigateToURL(net_util::FilePathToFileURL(path));
+
+ std::wstring title;
+ TabProxy* tab = GetActiveTab();
+ ASSERT_TRUE(tab);
+ EXPECT_TRUE(tab->GetTabTitle(&title));
+ EXPECT_EQ(L"Layout Test Plugin Test", title);
+
+ ASSERT_TRUE(tab->GoBack());
+ EXPECT_TRUE(tab->GetTabTitle(&title));
+ EXPECT_EQ(L"", title);
+
+ delete tab;
+}
diff --git a/chrome/test/ui/npapi_uitest.cpp b/chrome/test/ui/npapi_uitest.cpp
new file mode 100644
index 0000000..cf81db6
--- /dev/null
+++ b/chrome/test/ui/npapi_uitest.cpp
@@ -0,0 +1,281 @@
+// 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.
+
+//
+// NPAPI UnitTests.
+//
+
+// windows headers
+#include <windows.h>
+#include <shellapi.h>
+#include <shlobj.h>
+#include <atlbase.h>
+#include <comutil.h>
+
+// runtime headers
+#include <stdlib.h>
+#include <string.h>
+#include <memory.h>
+
+#include <ostream>
+
+#include "base/file_util.h"
+#include "chrome/common/chrome_paths.h"
+#include "chrome/test/automation/tab_proxy.h"
+#include "chrome/test/ui/ui_test.h"
+#include "net/base/net_util.h"
+
+const char kTestCompleteCookie[] = "status";
+const char kTestCompleteSuccess[] = "OK";
+const int kLongWaitTimeout = 30*1000;
+const int kShortWaitTimeout = 5*1000;
+
+std::ostream& operator<<(std::ostream& out, const CComBSTR &str)
+{
+ // I love strings. I really do. That's why I make sure
+ // to need 4 different types of strings to stream one out.
+ TCHAR szFinal[1024];
+ _bstr_t bstrIntermediate(str);
+ _stprintf_s(szFinal, _T("%s"), (LPCTSTR)bstrIntermediate);
+ return out << szFinal;
+}
+
+
+class NPAPITester : public UITest {
+ protected:
+ NPAPITester() : UITest()
+ {
+ }
+
+ virtual void SetUp()
+ {
+ // We need to copy our test-plugin into the plugins directory so that
+ // the browser can load it.
+ std::wstring plugins_directory = browser_directory_ + L"\\plugins";
+ std::wstring plugin_src = browser_directory_ + L"\\npapi_test_plugin.dll";
+ plugin_dll_ = plugins_directory + L"\\npapi_test_plugin.dll";
+
+ CreateDirectory(plugins_directory.c_str(), NULL);
+ CopyFile(plugin_src.c_str(), plugin_dll_.c_str(), FALSE);
+
+ UITest::SetUp();
+ }
+
+ virtual void TearDown()
+ {
+ DeleteFile(plugin_dll_.c_str());
+ UITest::TearDown();
+ }
+
+protected:
+ // Generate the URL for testing a particular test.
+ // HTML for the tests is all located in test_directory\npapi\<testcase>
+ GURL GetTestUrl(const std::wstring &test_case) {
+ std::wstring path;
+ PathService::Get(chrome::DIR_TEST_DATA, &path);
+ file_util::AppendToPath(&path, L"npapi");
+ file_util::AppendToPath(&path, test_case);
+ return net_util::FilePathToFileURL(path);
+ }
+
+ // Waits for the test case to finish.
+ // ASSERTS if there are test failures.
+ void WaitForFinish(const std::string &name, const std::string &id,
+ const GURL &url, const int wait_time)
+ {
+ const int kSleepTime = 250; // 4 times per second
+ const int kMaxIntervals = wait_time / kSleepTime;
+
+ scoped_ptr<TabProxy> tab(GetActiveTab());
+
+ std::string done_str;
+ for (int i = 0; i < kMaxIntervals; ++i) {
+ Sleep(kSleepTime);
+
+ // The webpage being tested has javascript which sets a cookie
+ // which signals completion of the test. The cookie name is
+ // a concatenation of the test name and the test id. This allows
+ // us to run multiple tests within a single webpage and test
+ // that they all c
+ std::string cookieName = name;
+ cookieName.append(".");
+ cookieName.append(id);
+ cookieName.append(".");
+ cookieName.append(kTestCompleteCookie);
+ tab->GetCookieByName(url, cookieName, &done_str);
+ if (!done_str.empty())
+ break;
+ }
+
+ EXPECT_EQ(kTestCompleteSuccess, done_str);
+ }
+
+private:
+ std::wstring plugin_dll_;
+};
+
+class NPAPIVisiblePluginTester : public NPAPITester {
+ protected:
+ virtual void SetUp() {
+ show_window_ = true;
+ NPAPITester::SetUp();
+ }
+};
+
+// Test passing arguments to a plugin.
+TEST_F(NPAPITester, Arguments) {
+ std::wstring test_case = L"arguments.html";
+ GURL url = GetTestUrl(test_case);
+ NavigateToURL(url);
+ WaitForFinish("arguments", "1", url, kShortWaitTimeout);
+}
+
+
+// Test invoking many plugins within a single page.
+TEST_F(NPAPITester, ManyPlugins) {
+ std::wstring test_case = L"many_plugins.html";
+ GURL url(GetTestUrl(test_case));
+ NavigateToURL(url);
+ WaitForFinish("arguments", "1", url, kShortWaitTimeout);
+ WaitForFinish("arguments", "2", url, kShortWaitTimeout);
+ WaitForFinish("arguments", "3", url, kShortWaitTimeout);
+ WaitForFinish("arguments", "4", url, kShortWaitTimeout);
+ WaitForFinish("arguments", "5", url, kShortWaitTimeout);
+ WaitForFinish("arguments", "6", url, kShortWaitTimeout);
+ WaitForFinish("arguments", "7", url, kShortWaitTimeout);
+ WaitForFinish("arguments", "8", url, kShortWaitTimeout);
+ WaitForFinish("arguments", "9", url, kShortWaitTimeout);
+ WaitForFinish("arguments", "10", url, kShortWaitTimeout);
+ WaitForFinish("arguments", "11", url, kShortWaitTimeout);
+ WaitForFinish("arguments", "12", url, kShortWaitTimeout);
+ WaitForFinish("arguments", "13", url, kShortWaitTimeout);
+ WaitForFinish("arguments", "14", url, kShortWaitTimeout);
+ WaitForFinish("arguments", "15", url, kShortWaitTimeout);
+}
+
+// Test various calls to GetURL from a plugin.
+TEST_F(NPAPITester, GetURL) {
+ std::wstring test_case = L"geturl.html";
+ GURL url = GetTestUrl(test_case);
+ NavigateToURL(url);
+ WaitForFinish("geturl", "1", url, kShortWaitTimeout);
+}
+
+// Test various calls to GetURL for javascript URLs with
+// non NULL targets from a plugin.
+TEST_F(NPAPITester, GetJavaScriptURL) {
+ std::wstring test_case = L"get_javascript_url.html";
+ GURL url = GetTestUrl(test_case);
+ NavigateToURL(url);
+ WaitForFinish("getjavascripturl", "1", url, kShortWaitTimeout);
+}
+
+
+// Tests that if an NPObject is proxies back to its original process, the
+// original pointer is returned and not a proxy. If this fails the plugin
+// will crash.
+TEST_F(NPAPITester, NPObjectProxy) {
+ std::wstring test_case = L"npobject_proxy.html";
+ GURL url = GetTestUrl(test_case);
+ NavigateToURL(url);
+ WaitForFinish("npobject_proxy", "1", url, kShortWaitTimeout);
+}
+
+// Tests if a plugin executing a self deleting script using NPN_GetURL
+// works without crashing or hanging
+TEST_F(NPAPITester, SelfDeletePluginGetUrl) {
+ std::wstring test_case = L"self_delete_plugin_geturl.html";
+ GURL url = GetTestUrl(test_case);
+ NavigateToURL(url);
+ WaitForFinish("self_delete_plugin_geturl", "1", url, kShortWaitTimeout);
+}
+
+// Tests if a plugin executing a self deleting script using Invoke
+// works without crashing or hanging
+TEST_F(NPAPITester, SelfDeletePluginInvoke) {
+ std::wstring test_case = L"self_delete_plugin_invoke.html";
+ GURL url = GetTestUrl(test_case);
+ NavigateToURL(url);
+ WaitForFinish("self_delete_plugin_invoke", "1", url, kShortWaitTimeout);
+}
+
+// Tests if a plugin executing a self deleting script in the context of
+// a synchronous paint event works correctly
+TEST_F(NPAPIVisiblePluginTester, SelfDeletePluginInvokeInSynchronousPaint) {
+ if (!UITest::in_process_plugins() && !UITest::in_process_renderer()) {
+ show_window_ = true;
+ std::wstring test_case = L"execute_script_delete_in_paint.html";
+ GURL url = GetTestUrl(test_case);
+ NavigateToURL(url);
+ WaitForFinish("execute_script_delete_in_paint", "1", url, kShortWaitTimeout);
+ }
+}
+
+TEST_F(NPAPIVisiblePluginTester, SelfDeletePluginInNewStream) {
+ show_window_ = true;
+ std::wstring test_case = L"self_delete_plugin_stream.html";
+ GURL url = GetTestUrl(test_case);
+ NavigateToURL(url);
+ WaitForFinish("self_delete_plugin_stream", "1", url, kShortWaitTimeout);
+}
+
+// Tests if a plugin has a non zero window rect.
+TEST_F(NPAPIVisiblePluginTester, VerifyPluginWindowRect) {
+ show_window_ = true;
+ std::wstring test_case = L"verify_plugin_window_rect.html";
+ GURL url = GetTestUrl(test_case);
+ NavigateToURL(url);
+ WaitForFinish("checkwindowrect", "1", url, kShortWaitTimeout);
+}
+
+TEST_F(NPAPIVisiblePluginTester, VerifyNPObjectLifetimeTest) {
+ if (!UITest::in_process_plugins() && !UITest::in_process_renderer()) {
+ show_window_ = true;
+ std::wstring test_case = L"npobject_lifetime_test.html";
+ GURL url = GetTestUrl(test_case);
+ NavigateToURL(url);
+ WaitForFinish("npobject_lifetime_test", "1", url, kShortWaitTimeout);
+ }
+}
+
+// Tests that we don't crash or assert if NPP_New fails
+TEST_F(NPAPIVisiblePluginTester, NewFails) {
+ GURL url = GetTestUrl(L"new_fails.html");
+ NavigateToURL(url);
+ WaitForFinish("new_fails", "1", url, kShortWaitTimeout);
+}
+
+TEST_F(NPAPIVisiblePluginTester, SelfDeletePluginInNPNEvaluate) {
+ if (!UITest::in_process_plugins() && !UITest::in_process_renderer()) {
+ GURL url = GetTestUrl(L"execute_script_delete_in_npn_evaluate.html");
+ NavigateToURL(url);
+ WaitForFinish("npobject_delete_plugin_in_evaluate", "1", url,
+ kShortWaitTimeout);
+ }
+} \ No newline at end of file
diff --git a/chrome/test/ui/omnibox_uitest.cc b/chrome/test/ui/omnibox_uitest.cc
new file mode 100644
index 0000000..933810e
--- /dev/null
+++ b/chrome/test/ui/omnibox_uitest.cc
@@ -0,0 +1,203 @@
+// 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.
+
+#include <stdio.h>
+
+#include "base/command_line.h"
+#include "base/file_util.h"
+#include "base/path_service.h"
+#include "base/perftimer.h"
+#include "base/string_util.h"
+#include "chrome/app/chrome_dll_resource.h"
+#include "chrome/common/chrome_paths.h"
+#include "chrome/common/libxml_utils.h"
+#include "chrome/test/automation/autocomplete_edit_proxy.h"
+#include "chrome/test/automation/automation_proxy.h"
+#include "chrome/test/automation/browser_proxy.h"
+#include "chrome/test/automation/window_proxy.h"
+#include "chrome/test/ui/ui_test.h"
+
+const wchar_t kRunOmniboxTest[] = L"run_omnibox_test";
+
+class OmniboxTest : public UITest {
+ public:
+
+ double score_;
+ double max_score_;
+
+ int query_count_;
+ int query_timeouts_;
+ int64 time_squared_;
+ int64 time_sum_;
+ int64 time_min_;
+ int64 time_max_;
+
+ OmniboxTest() : UITest() {
+ show_window_ = true;
+ query_count_ = 0;
+ query_timeouts_ = 0;
+ score_ = 0;
+ max_score_ = 0;
+ time_squared_ = 0;
+ time_sum_ = 0;
+ time_min_ = 0;
+ time_max_ = 0;
+ }
+
+ // Many times a user may enter something like "google.com". If
+ // http://www.google.com/ is suggested that should be considered a match.
+ // This could probably be accomplished with regex as well. Note that this
+ // method is called even when suggestion isn't a URL.
+ bool IsMatch(const std::wstring& input_test, const std::wstring& suggestion);
+ // Runs a query chain. This sends each proper prefix of the input to the
+ // omnibox and scores the autocompelte results returned.
+ void RunQueryChain(const std::wstring& input_text);
+};
+
+bool OmniboxTest::IsMatch(const std::wstring& input_text,
+ const std::wstring& suggestion) {
+ // This prefix list comes from the list used in history_url_provider.cc withiff
+ // the exception of "ftp." and "www.".
+ std::wstring prefixes[] = {L"", L"ftp://", L"http://", L"https://",
+ L"ftp.", L"www.", L"ftp://www.", L"ftp://ftp.",
+ L"http://www.", L"https://www."};
+ std::wstring postfixes[] = {L"", L"/"};
+ for (int i = 0; i < sizeof(prefixes) / sizeof(std::wstring); ++i) {
+ for (int j = 0; j < sizeof(postfixes) / sizeof(std::wstring); ++j) {
+ if (prefixes[i] + input_text + postfixes[j] == suggestion)
+ return true;
+ }
+ }
+ return false;
+}
+
+void OmniboxTest::RunQueryChain(const std::wstring& input_text) {
+ // Get a handle on the omnibox and give it focus.
+ scoped_ptr<BrowserProxy> browser(automation()->GetBrowserWindow(0));
+ scoped_ptr<WindowProxy> window(
+ automation()->GetWindowForBrowser(browser.get()));
+ scoped_ptr<AutocompleteEditProxy> autocomplete_edit(
+ automation()->GetAutocompleteEditForBrowser(browser.get()));
+ ASSERT_TRUE(browser->ApplyAccelerator(IDC_FOCUS_LOCATION));
+
+ // Try every proper prefix of input_text. There's no use trying
+ // input_text itself since the autocomplete results will always contain it.
+ for (size_t i = 1; i < input_text.size(); ++i) {
+ Matches matches;
+
+ // We're only going to count the time elapsed waiting for autocomplete
+ // matches to be returned to us.
+ ASSERT_TRUE(autocomplete_edit->SetText(input_text.substr(0, i)));
+ PerfTimer timer;
+ if (autocomplete_edit->WaitForQuery(30000)) {
+ ASSERT_TRUE(autocomplete_edit->GetAutocompleteMatches(&matches));
+ int64 time_elapsed = timer.Elapsed().InMilliseconds();
+
+ // Adjust statistic trackers.
+ if (query_count_ == 0)
+ time_min_ = time_max_ = time_elapsed;
+ ++query_count_;
+ time_squared_ += time_elapsed * time_elapsed;
+ time_sum_ += time_elapsed;
+ if (time_elapsed < time_min_)
+ time_min_ = time_elapsed;
+ if (time_elapsed > time_max_)
+ time_max_ = time_elapsed;
+ } else {
+ ++query_timeouts_;
+ }
+ wprintf(L"query: %d\n", query_count_);
+
+ // Check if any suggestions match the input text. Stop if a match is
+ // found.
+ for (Matches::const_iterator j(matches.begin()); j != matches.end(); ++j) {
+ if (IsMatch(input_text, j->fill_into_edit)) {
+ score_ += i;
+ break;
+ }
+ }
+ max_score_ += i;
+ }
+}
+
+// This test reads in the omnibox_tests.xml file and performs the tests
+// within. The current format of xml is fairly simple. Nothing is currently
+// done with the provider information.
+// <omnibox_tests>
+// Zero or more test elements.
+// <test query='%query%'>
+// Zero or more provider elements.
+// <provider name='%expected_provider_name%'/>
+// </test>
+// </omnibox_tests>
+
+TEST_F(OmniboxTest, Measure) {
+ if (!CommandLine().HasSwitch(kRunOmniboxTest)) return;
+
+ std::wstring omnibox_tests_path;
+ PathService::Get(chrome::DIR_TEST_DATA, &omnibox_tests_path);
+ file_util::AppendToPath(&omnibox_tests_path, L"omnibox_tests.xml");
+
+ XmlReader reader;
+ ASSERT_TRUE(reader.LoadFile(WideToASCII(omnibox_tests_path)));
+ while (reader.SkipToElement()) {
+ ASSERT_EQ("omnibox_tests", reader.NodeName());
+ reader.Read();
+ while (reader.SkipToElement()) {
+ ASSERT_EQ("test", reader.NodeName());
+ std::string query;
+ std::vector<std::string> expected_providers;
+ ASSERT_TRUE(reader.NodeAttribute("query", &query));
+ reader.Read();
+ while (reader.SkipToElement()) {
+ ASSERT_EQ("provider", reader.NodeName());
+ std::string provider;
+ ASSERT_TRUE(reader.NodeAttribute("provider", &provider));
+ expected_providers.push_back(provider);
+ reader.Read();
+ }
+ RunQueryChain(ASCIIToWide(query));
+ reader.Read();
+ }
+ reader.Read();
+ }
+
+ // Output results.
+ ASSERT_GT(query_count_, 0);
+ int64 mean = time_sum_ / query_count_;
+ wprintf(L"__om_query_count = %d\n", query_count_);
+ wprintf(L"__om_query_timeouts = %d\n", query_timeouts_);
+ wprintf(L"__om_time_per_query_avg = %d\n", mean);
+ // Use the equation stddev = sqrt(Sum(x_i^2)/N - mean^2).
+ wprintf(L"__om_time_per_query_stddev = %d\n", static_cast<int64>(
+ sqrt(1.0 * time_squared_ / query_count_ - mean * mean)));
+ wprintf(L"__om_time_per_query_max = %d\n", time_max_);
+ wprintf(L"__om_time_per_query_min = %d\n", time_min_);
+ wprintf(L"__om_score = %.4f\n", 100.0 * score_ / max_score_);
+}
diff --git a/chrome/test/ui/run_all_unittests.cc b/chrome/test/ui/run_all_unittests.cc
new file mode 100644
index 0000000..737a7be
--- /dev/null
+++ b/chrome/test/ui/run_all_unittests.cc
@@ -0,0 +1,35 @@
+// 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.
+
+#include "chrome/test/ui/ui_test_suite.h"
+
+int main(int argc, char **argv) {
+ Thread::SetThreadName("Tests_Main", GetCurrentThreadId());
+ return UITestSuite(argc, argv).Run();
+}
diff --git a/chrome/test/ui/sandbox_uitests.cc b/chrome/test/ui/sandbox_uitests.cc
new file mode 100644
index 0000000..2c30ba8
--- /dev/null
+++ b/chrome/test/ui/sandbox_uitests.cc
@@ -0,0 +1,51 @@
+// 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.
+
+#include <windows.h>
+#include <string>
+
+#include "base/command_line.h"
+#include "chrome/common/chrome_switches.h"
+#include "chrome/test/ui/ui_test.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+class SandboxTest : public UITest {
+ protected:
+ // Launches chrome with the --test-sandbox=security_tests.dll flag.
+ SandboxTest() : UITest() {
+ CommandLine::AppendSwitchWithValue(&launch_arguments_,
+ switches::kTestSandbox,
+ L"security_tests.dll");
+ }
+};
+
+// Verifies that chrome is running properly.
+TEST_F(SandboxTest, ExecuteDll) {
+ EXPECT_EQ(1, GetTabCount());
+}
diff --git a/chrome/test/ui/ui_test.cc b/chrome/test/ui/ui_test.cc
new file mode 100644
index 0000000..f5ce685
--- /dev/null
+++ b/chrome/test/ui/ui_test.cc
@@ -0,0 +1,554 @@
+// 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.
+
+#include <set>
+#include <vector>
+
+#include "chrome/test/ui/ui_test.h"
+
+#include "base/base_switches.h"
+#include "base/command_line.h"
+#include "base/file_util.h"
+#include "base/process_util.h"
+#include "base/scoped_ptr.h"
+#include "base/string_util.h"
+#include "base/time.h"
+#include "chrome/browser/url_fixer_upper.h"
+#include "chrome/common/chrome_constants.h"
+#include "chrome/common/chrome_paths.h"
+#include "chrome/common/chrome_process_filter.h"
+#include "chrome/common/chrome_switches.h"
+#include "chrome/common/debug_flags.h"
+#include "chrome/common/logging_chrome.h"
+#include "chrome/common/json_value_serializer.h"
+#include "chrome/test/automation/browser_proxy.h"
+#include "chrome/test/automation/tab_proxy.h"
+#include "chrome/test/automation/window_proxy.h"
+#include "chrome/test/test_file_util.h"
+
+bool UITest::in_process_renderer_ = false;
+bool UITest::in_process_plugins_ = false;
+bool UITest::no_sandbox_ = false;
+bool UITest::full_memory_dump_ = false;
+bool UITest::safe_plugins_ = false;
+bool UITest::show_error_dialogs_ = true;
+bool UITest::default_use_existing_browser_ = false;
+bool UITest::dump_histograms_on_exit_ = false;
+bool UITest::enable_dcheck_ = false;
+bool UITest::silent_dump_on_dcheck_ = false;
+int UITest::timeout_ms_ = 20 * 60 * 1000;
+
+// Uncomment this line to have the spawned process wait for the debugger to
+// attach.
+// #define WAIT_FOR_DEBUGGER_ON_OPEN 1
+
+// static
+bool UITest::DieFileDie(const std::wstring& file, bool recurse) {
+ if (!file_util::PathExists(file))
+ return true;
+
+ // Sometimes Delete fails, so try a few more times.
+ for (int i = 0; i < 10; ++i) {
+ if (file_util::Delete(file, recurse))
+ return true;
+ Sleep(kWaitForActionMaxMsec / 10);
+ }
+ return false;
+}
+
+UITest::UITest()
+ : testing::Test(),
+ expected_errors_(0),
+ expected_crashes_(0),
+ wait_for_initial_loads_(true),
+ homepage_(L"about:blank"),
+ dom_automation_enabled_(false),
+ process_(NULL),
+ show_window_(false),
+ clear_profile_(true),
+ include_testing_id_(true),
+ use_existing_browser_(default_use_existing_browser_) {
+ PathService::Get(chrome::DIR_APP, &browser_directory_);
+ PathService::Get(chrome::DIR_TEST_DATA, &test_data_directory_);
+ GetSystemTimeAsFileTime(&test_start_time_);
+}
+
+void UITest::SetUp() {
+ if (!use_existing_browser_) {
+ AssertAppNotRunning(L"Please close any other instances "
+ L"of the app before testing.");
+ }
+
+ LaunchBrowserAndServer();
+}
+
+void UITest::TearDown() {
+ CloseBrowserAndServer();
+
+ // Make sure that we didn't encounter any assertion failures
+ logging::AssertionList assertions;
+ logging::GetFatalAssertions(&assertions);
+
+ // If there were errors, get all the error strings for display.
+ std::wstring failures =
+ L"The following error(s) occurred in the application during this test:";
+ if (static_cast<int>(assertions.size()) > expected_errors_) {
+ logging::AssertionList::const_iterator iter = assertions.begin();
+ for (; iter != assertions.end(); ++iter) {
+ failures.append(L"\n\n");
+ failures.append(*iter);
+ }
+ }
+ EXPECT_EQ(expected_errors_, assertions.size()) << failures;
+
+ // Check for crashes during the test
+ std::wstring crash_dump_path;
+ PathService::Get(chrome::DIR_CRASH_DUMPS, &crash_dump_path);
+ // Each crash creates two dump files, so we divide by two here.
+ int actual_crashes =
+ file_util::CountFilesCreatedAfter(crash_dump_path, test_start_time_) / 2;
+ std::wstring error_msg =
+ L"Encountered an unexpected crash in the program during this test.";
+ if (expected_crashes_ > 0 && actual_crashes == 0)
+ error_msg += L" Have you started crash_service.exe?";
+ EXPECT_EQ(expected_crashes_, actual_crashes) << error_msg;
+}
+
+void UITest::LaunchBrowserAndServer() {
+ // Set up IPC testing interface server.
+ server_.reset(new AutomationProxy);
+
+ LaunchBrowser(launch_arguments_, clear_profile_);
+ if (wait_for_initial_loads_)
+ ASSERT_TRUE(server_->WaitForInitialLoads());
+ else
+ Sleep(2000);
+
+ automation()->SetFilteredInet(true);
+}
+
+void UITest::CloseBrowserAndServer() {
+ QuitBrowser();
+ CleanupAppProcesses();
+
+ // Shut down IPC testing interface.
+ server_.reset();
+}
+
+void UITest::LaunchBrowser(const std::wstring& arguments, bool clear_profile) {
+ std::wstring command_line(browser_directory_);
+ file_util::AppendToPath(&command_line,
+ chrome::kBrowserProcessExecutableName);
+
+ // We need cookies on file:// for things like the page cycler.
+ CommandLine::AppendSwitch(&command_line, switches::kEnableFileCookies);
+
+ if (dom_automation_enabled_)
+ CommandLine::AppendSwitch(&command_line,
+ switches::kDomAutomationController);
+
+ if (include_testing_id_) {
+ if (use_existing_browser_) {
+ // TODO(erikkay): The new switch depends on a browser instance already
+ // running, it won't open a new browser window if it's not. We could fix
+ // this by passing an url (e.g. about:blank) on the command line, but
+ // I decided to keep using the old switch in the existing use case to
+ // minimize changes in behavior.
+ CommandLine::AppendSwitchWithValue(&command_line,
+ switches::kAutomationClientChannelID,
+ server_->channel_id());
+ } else {
+ CommandLine::AppendSwitchWithValue(&command_line,
+ switches::kTestingChannelID,
+ server_->channel_id());
+ }
+ }
+
+ if (!show_error_dialogs_)
+ CommandLine::AppendSwitch(&command_line, switches::kNoErrorDialogs);
+ if (in_process_renderer_)
+ CommandLine::AppendSwitch(&command_line, switches::kSingleProcess);
+ if (in_process_plugins_)
+ CommandLine::AppendSwitch(&command_line, switches::kInProcessPlugins);
+ if (no_sandbox_)
+ CommandLine::AppendSwitch(&command_line, switches::kNoSandbox);
+ if (full_memory_dump_)
+ CommandLine::AppendSwitch(&command_line, switches::kFullMemoryCrashReport);
+ if (safe_plugins_)
+ CommandLine::AppendSwitch(&command_line, switches::kSafePlugins);
+ if (enable_dcheck_)
+ CommandLine::AppendSwitch(&command_line, switches::kEnableDCHECK);
+ if (silent_dump_on_dcheck_)
+ CommandLine::AppendSwitch(&command_line, switches::kSilentDumpOnDCHECK);
+ if (!homepage_.empty())
+ CommandLine::AppendSwitchWithValue(&command_line,
+ switches::kHomePage,
+ homepage_);
+ PathService::Get(chrome::DIR_USER_DATA, &user_data_dir_);
+ if (!user_data_dir_.empty())
+ CommandLine::AppendSwitchWithValue(&command_line,
+ switches::kUserDataDir,
+ user_data_dir_);
+
+ CommandLine::AppendSwitch(&command_line, switches::kDisableMetricsReporting);
+
+ // We always want to enable chrome logging
+ CommandLine::AppendSwitch(&command_line, switches::kEnableLogging);
+
+ if (dump_histograms_on_exit_)
+ CommandLine::AppendSwitch(&command_line, switches::kDumpHistogramsOnExit);
+
+#ifdef WAIT_FOR_DEBUGGER_ON_OPEN
+ CommandLine::AppendSwitch(&command_line, switches::kDebugOnStart);
+#endif
+
+ DebugFlags::ProcessDebugFlags(&command_line, DebugFlags::UNKNOWN, false);
+ command_line.append(L" " + arguments);
+
+ // Clear user data directory to make sure test environment is consistent
+ // We balk on really short (absolute) user_data_dir directory names, because
+ // we're worried that they'd accidentally be root or something.
+ ASSERT_LT(10, static_cast<int>(user_data_dir_.size())) <<
+ "The user data directory name passed into this test was too "
+ "short to delete safely. Please check the user-data-dir "
+ "argument and try again.";
+ if (clear_profile)
+ ASSERT_TRUE(DieFileDie(user_data_dir_, true));
+
+ if (!template_user_data_.empty()) {
+ // Recursively copy the template directory to the user_data_dir.
+ ASSERT_TRUE(file_util::CopyRecursiveDirNoCache(template_user_data_,
+ user_data_dir_));
+ }
+
+ browser_launch_time_ = TimeTicks::Now();
+
+ bool started = process_util::LaunchApp(
+ command_line,
+ false, // Don't wait for process object (doesn't work for
+ // us)
+ !show_window_,
+ &process_);
+ ASSERT_EQ(started, true);
+
+ if (use_existing_browser_) {
+ DWORD pid = 0;
+ HWND hwnd = FindWindowEx(HWND_MESSAGE, NULL, chrome::kMessageWindowClass,
+ user_data_dir_.c_str());
+ GetWindowThreadProcessId(hwnd, &pid);
+ // This mode doesn't work if we wound up launching a new browser ourselves.
+ ASSERT_NE(pid, process_util::GetProcId(process_));
+ CloseHandle(process_);
+ process_ = OpenProcess(SYNCHRONIZE, false, pid);
+ }
+}
+
+void UITest::QuitBrowser() {
+ typedef std::vector<HWND> HandleVector;
+
+ // There's nothing to do here if the browser is not running.
+ if (IsBrowserRunning()) {
+ automation()->SetFilteredInet(false);
+ HandleVector handles;
+
+ // Build up a list of HWNDs; we do this as a separate step so that closing
+ // the windows doesn't mess up the iteration.
+ int window_count = 0;
+ EXPECT_TRUE(automation()->GetBrowserWindowCount(&window_count));
+
+ for (int i = 0; i < window_count; ++i) {
+ HWND window_handle;
+ scoped_ptr<BrowserProxy> browser(automation()->GetBrowserWindow(i));
+ scoped_ptr<WindowProxy> window(
+ automation()->GetWindowForBrowser(browser.get()));
+ EXPECT_TRUE(window->GetHWND(&window_handle));
+ handles.push_back(window_handle);
+ }
+
+ for (HandleVector::iterator iter = handles.begin(); iter != handles.end();
+ ++iter) {
+ ::PostMessage(*iter, WM_CLOSE, 0, 0);
+ }
+
+ // Wait for the browser process to quit. It should quit once all tabs have
+ // been closed.
+ int timeout = 5000;
+#ifdef WAIT_FOR_DEBUGGER_ON_OPEN
+ timeout = 500000;
+#endif
+ if (WAIT_TIMEOUT == WaitForSingleObject(process_, timeout)) {
+ // We need to force the browser to quit because it didn't quit fast
+ // enough. Take no chance and kill every chrome processes.
+ CleanupAppProcesses();
+ }
+ }
+
+ // Don't forget to close the handle
+ CloseHandle(process_);
+ process_ = NULL;
+}
+
+void UITest::AssertAppNotRunning(const std::wstring& error_message) {
+ ASSERT_EQ(0, GetBrowserProcessCount()) << error_message;
+}
+
+void UITest::CleanupAppProcesses() {
+ BrowserProcessFilter filter;
+
+ // Make sure that no instances of the browser remain.
+ const int kExitTimeoutMs = 5000;
+ const int kExitCode = 1;
+ process_util::CleanupProcesses(
+ chrome::kBrowserProcessExecutableName, kExitTimeoutMs, kExitCode,
+ &filter);
+
+ // Suppress spammy failures that seem to be occurring when running
+ // the UI tests in single-process mode.
+ // TODO(jhughes): figure out why this is necessary at all, and fix it
+ if (!in_process_renderer_) {
+ AssertAppNotRunning(L"Unable to quit all browser processes.");
+ }
+}
+
+TabProxy* UITest::GetActiveTab() {
+ scoped_ptr<BrowserProxy> window_proxy(automation()->GetBrowserWindow(0));
+ if (!window_proxy.get())
+ return NULL;
+
+ int active_tab_index = -1;
+ EXPECT_TRUE(window_proxy->GetActiveTabIndex(&active_tab_index));
+ if (active_tab_index == -1)
+ return NULL;
+
+ return window_proxy->GetTab(active_tab_index);
+}
+
+void UITest::NavigateToURL(const GURL& url) {
+ scoped_ptr<TabProxy> tab_proxy(GetActiveTab());
+ ASSERT_TRUE(tab_proxy.get());
+ if (!tab_proxy.get())
+ return;
+
+ bool is_timeout = true;
+ ASSERT_TRUE(tab_proxy->NavigateToURLWithTimeout(url, kMaxTestExecutionTime,
+ &is_timeout)) << url.spec();
+ ASSERT_FALSE(is_timeout) << url.spec();
+}
+
+bool UITest::WaitForDownloadShelfVisible(TabProxy* tab) {
+ const int kCycles = 20;
+ for (int i = 0; i < kCycles; i++) {
+ bool visible = false;
+ if (!tab->IsShelfVisible(&visible))
+ return false; // Some error.
+ if (visible)
+ return true; // Got the download shelf.
+
+ // Give it a chance to catch up.
+ Sleep(kWaitForActionMaxMsec / kCycles);
+ }
+ return false;
+}
+
+GURL UITest::GetActiveTabURL() {
+ scoped_ptr<TabProxy> tab_proxy(GetActiveTab());
+ if (!tab_proxy.get())
+ return GURL();
+
+ GURL url;
+ if (!tab_proxy->GetCurrentURL(&url))
+ return GURL();
+ return url;
+}
+
+std::wstring UITest::GetActiveTabTitle() {
+ std::wstring title;
+ scoped_ptr<TabProxy> tab_proxy(GetActiveTab());
+ if (!tab_proxy.get())
+ return title;
+
+ EXPECT_TRUE(tab_proxy->GetTabTitle(&title));
+ return title;
+}
+
+bool UITest::IsBrowserRunning() {
+ return CrashAwareSleep(0);
+}
+
+bool UITest::CrashAwareSleep(int time_out_ms) {
+ return WAIT_TIMEOUT == WaitForSingleObject(process_, time_out_ms);
+}
+
+/*static*/
+int UITest::GetBrowserProcessCount() {
+ BrowserProcessFilter filter;
+ return process_util::GetProcessCount(chrome::kBrowserProcessExecutableName,
+ &filter);
+}
+
+static DictionaryValue* LoadDictionaryValueFromPath(const std::wstring& path) {
+ if (path.empty())
+ return NULL;
+
+ JSONFileValueSerializer serializer(path);
+ Value* root_value = NULL;
+ if (serializer.Deserialize(&root_value) &&
+ root_value->GetType() != Value::TYPE_DICTIONARY) {
+ delete root_value;
+ return NULL;
+ }
+ return static_cast<DictionaryValue*>(root_value);
+}
+
+DictionaryValue* UITest::GetLocalState() {
+ std::wstring local_state_path;
+ PathService::Get(chrome::FILE_LOCAL_STATE, &local_state_path);
+ return LoadDictionaryValueFromPath(local_state_path);
+}
+
+DictionaryValue* UITest::GetDefaultProfilePreferences() {
+ std::wstring path;
+ PathService::Get(chrome::DIR_USER_DATA, &path);
+ file_util::AppendToPath(&path, chrome::kNotSignedInProfile);
+ file_util::AppendToPath(&path, chrome::kPreferencesFilename);
+ return LoadDictionaryValueFromPath(path);
+}
+
+int UITest::GetTabCount() {
+ scoped_ptr<BrowserProxy> first_window(automation()->GetBrowserWindow(0));
+ if (!first_window.get())
+ return 0;
+
+ int result = 0;
+ EXPECT_TRUE(first_window->GetTabCount(&result));
+
+ return result;
+}
+
+bool UITest::WaitUntilCookieValue(TabProxy* tab,
+ const GURL& url,
+ const char* cookie_name,
+ int interval_ms,
+ int time_out_ms,
+ const char* expected_value) {
+ const int kMaxIntervals = time_out_ms / interval_ms;
+
+ std::string cookie_value;
+ bool completed = false;
+ for (int i = 0; i < kMaxIntervals; ++i) {
+ bool browser_survived = CrashAwareSleep(interval_ms);
+
+ tab->GetCookieByName(url, cookie_name, &cookie_value);
+
+ if (cookie_value == expected_value) {
+ completed = true;
+ break;
+ }
+ EXPECT_TRUE(browser_survived);
+ if (!browser_survived) {
+ // The browser process died.
+ break;
+ }
+ }
+ return completed;
+}
+
+std::string UITest::WaitUntilCookieNonEmpty(TabProxy* tab,
+ const GURL& url,
+ const char* cookie_name,
+ int interval_ms,
+ int time_out_ms) {
+ const int kMaxIntervals = time_out_ms / interval_ms;
+
+ std::string cookie_value;
+ for (int i = 0; i < kMaxIntervals; ++i) {
+ bool browser_survived = CrashAwareSleep(interval_ms);
+
+ tab->GetCookieByName(url, cookie_name, &cookie_value);
+
+ if (!cookie_value.empty())
+ break;
+
+ EXPECT_TRUE(browser_survived);
+ if (!browser_survived) {
+ // The browser process died.
+ break;
+ }
+ }
+
+ return cookie_value;
+}
+
+void UITest::WaitUntilTabCount(int tab_count) {
+ for (int i = 0; i < 10; ++i) {
+ Sleep(kWaitForActionMaxMsec / 10);
+ if (GetTabCount() == tab_count)
+ break;
+ }
+ EXPECT_EQ(tab_count, GetTabCount());
+}
+
+std::wstring UITest::GetDownloadDirectory() {
+ scoped_ptr<TabProxy> tab_proxy(GetActiveTab());
+ if (!tab_proxy.get())
+ return false;
+
+ std::wstring download_directory;
+ EXPECT_TRUE(tab_proxy->GetDownloadDirectory(&download_directory));
+ return download_directory;
+}
+
+bool UITest::CloseBrowser(BrowserProxy* browser,
+ bool* application_closed) const {
+ DCHECK(application_closed);
+ if (!browser->is_valid() || !browser->handle())
+ return false;
+
+ IPC::Message* response = NULL;
+ bool succeeded = server_->SendAndWaitForResponse(
+ new AutomationMsg_CloseBrowserRequest(0, browser->handle()),
+ &response, AutomationMsg_CloseBrowserResponse__ID);
+
+ if (!succeeded)
+ return false;
+
+ void* iter = NULL;
+ bool result = true;
+ response->ReadBool(&iter, &result);
+ response->ReadBool(&iter, application_closed);
+
+ if (*application_closed) {
+ // Let's wait until the process dies (if it is not gone already).
+ int r = WaitForSingleObject(process_, INFINITE);
+ DCHECK(r != WAIT_FAILED);
+ }
+
+ delete response;
+ return result;
+}
diff --git a/chrome/test/ui/ui_test.h b/chrome/test/ui/ui_test.h
new file mode 100644
index 0000000..daaff3d
--- /dev/null
+++ b/chrome/test/ui/ui_test.h
@@ -0,0 +1,344 @@
+// 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.
+
+#ifndef CHROME_TEST_UI_UI_TEST_H__
+#define CHROME_TEST_UI_UI_TEST_H__
+
+// This file provides a common base for running UI unit tests, which operate
+// the entire browser application in a separate process for holistic
+// functional testing.
+//
+// Tests should #include this file, subclass UITest, and use the TEST_F macro
+// to declare individual test cases. This provides a running browser window
+// during the test, accessible through the window_ member variable. The window
+// will close when the test ends, regardless of whether the test passed.
+//
+// Tests which need to launch the browser with a particular set of command-line
+// arguments should set the value of launch_arguments_ in their constructors.
+
+#include <windows.h>
+#include <string>
+
+#include "base/path_service.h"
+#include "base/scoped_ptr.h"
+#include "base/time.h"
+#include "chrome/test/automation/automation_proxy.h"
+#include "googleurl/src/gurl.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+class DictionaryValue;
+class TabProxy;
+
+class UITest : public testing::Test {
+ protected:
+ // Delay to let browser complete a requested action.
+ static const int kWaitForActionMsec = 2000;
+ static const int kWaitForActionMaxMsec = 10000;
+ // Delay to let the browser complete the test.
+ static const int kMaxTestExecutionTime = 30000;
+
+ // Tries to delete the specified file/directory returning true on success.
+ // This differs from file_util::Delete in that it repeatedly invokes Delete
+ // until successful, or a timeout is reached. Returns true on success.
+ static bool DieFileDie(const std::wstring& file, bool recurse);
+
+ // Constructor
+ UITest();
+
+ // Starts the browser using the arguments in launch_arguments_, and
+ // sets up member variables.
+ virtual void SetUp();
+
+ // Closes the browser window.
+ virtual void TearDown();
+
+ // ********* Utility functions *********
+
+ // Launches the browser and IPC testing server.
+ void LaunchBrowserAndServer();
+
+ // Closes the browser and IPC testing server.
+ void CloseBrowserAndServer();
+
+ // Launches the browser with the given arguments.
+ void LaunchBrowser(const std::wstring& arguments, bool clear_profile);
+
+ // Exits out browser instance.
+ void QuitBrowser();
+
+ // Tells the browser to navigate to the given URL in the active tab
+ // of the first app window.
+ // This method doesn't return until the navigation is complete.
+ void NavigateToURL(const GURL& url);
+
+ // Returns the URL of the currently active tab. If there is no active tab,
+ // or some other error, the returned URL will be empty.
+ GURL GetActiveTabURL();
+
+ // Returns the title of the currently active tab.
+ std::wstring GetActiveTabTitle();
+
+ // Returns true when the browser process is running, independent if any
+ // renderer process exists or not. It will returns false if an user closed the
+ // window or if the browser process died by itself.
+ bool IsBrowserRunning();
+
+ // Returns true when time_out_ms milliseconds have elapsed.
+ // Returns false if the browser process died while waiting.
+ bool CrashAwareSleep(int time_out_ms);
+
+ // Returns the number of tabs in the first window. If no windows exist,
+ // causes a test failure and returns 0.
+ int GetTabCount();
+
+ // Polls the tab for the cookie_name cookie and returns once one of the
+ // following conditions hold true:
+ // - The cookie is of expected_value.
+ // - The browser process died.
+ // - The time_out value has been exceeded.
+ bool WaitUntilCookieValue(TabProxy* tab, const GURL& url,
+ const char* cookie_name,
+ int interval_ms,
+ int time_out_ms,
+ const char* expected_value);
+ // Polls the tab for the cookie_name cookie and returns once one of the
+ // following conditions hold true:
+ // - The cookie is set to any value.
+ // - The browser process died.
+ // - The time_out value has been exceeded.
+ std::string WaitUntilCookieNonEmpty(TabProxy* tab,
+ const GURL& url,
+ const char* cookie_name,
+ int interval_ms,
+ int time_out_ms);
+
+ // Polls up to kWaitForActionMaxMsec ms to attain a specific tab count. Will
+ // assert that the tab count is valid at the end of the wait.
+ void WaitUntilTabCount(int tab_count);
+
+ // Checks whether the download shelf is visible in the current tab, giving it
+ // a chance to appear (we don't know the exact timing) while finishing as soon
+ // as possible.
+ bool WaitForDownloadShelfVisible(TabProxy* tab);
+
+ // Closes the specified browser. Returns true if the browser was closed.
+ // This call is blocking. |application_closed| is set to true if this was
+ // the last browser window (and therefore as a result of it closing the
+ // browser process terminated). Note that in that case this method returns
+ // after the browser process has terminated.
+ bool CloseBrowser(BrowserProxy* browser, bool* application_closed) const;
+
+ // Gets the directory for the currently active profile in the browser.
+ std::wstring GetDownloadDirectory();
+
+ // Get the handle of browser process connected to the automation. This
+ // function only retruns a reference to the handle so the caller does not
+ // own the handle returned.
+ HANDLE process() { return process_; }
+
+ public:
+ // Get/Set a flag to run the renderer in process when running the
+ // tests.
+ static bool in_process_renderer() { return in_process_renderer_; }
+ static void set_in_process_renderer(bool value) {
+ in_process_renderer_ = value;
+ }
+
+ // Get/Set a flag to run the plugins in the renderer process when running the
+ // tests.
+ static bool in_process_plugins() { return in_process_plugins_; }
+ static void set_in_process_plugins(bool value) {
+ in_process_plugins_ = value;
+ }
+
+ // Get/Set a flag to run the renderer outside the sandbox when running the
+ // tests
+ static bool no_sandbox() { return no_sandbox_; }
+ static void set_no_sandbox(bool value) {
+ no_sandbox_ = value;
+ }
+
+ // Get/Set a flag to run with DCHECKs enabled in release.
+ static bool enable_dcheck() { return enable_dcheck_; }
+ static void set_enable_dcheck(bool value) {
+ enable_dcheck_ = value;
+ }
+
+ // Get/Set a flag to dump the process memory without crashing on DCHECKs.
+ static bool silent_dump_on_dcheck() { return silent_dump_on_dcheck_; }
+ static void set_silent_dump_on_dcheck(bool value) {
+ silent_dump_on_dcheck_ = value;
+ }
+
+ // Get/Set a flag to run the plugin processes inside the sandbox when running
+ // the tests
+ static bool safe_plugins() { return safe_plugins_; }
+ static void set_safe_plugins(bool value) {
+ safe_plugins_ = value;
+ }
+
+ static bool show_error_dialogs() { return show_error_dialogs_; }
+ static void set_show_error_dialogs(bool value) {
+ show_error_dialogs_ = value;
+ }
+
+ static bool full_memory_dump() { return full_memory_dump_; }
+ static void set_full_memory_dump(bool value) {
+ full_memory_dump_ = value;
+ }
+
+ static bool use_existing_browser() { return default_use_existing_browser_; }
+ static void set_use_existing_browser(bool value) {
+ default_use_existing_browser_ = value;
+ }
+
+ static bool dump_histograms_on_exit() { return dump_histograms_on_exit_; }
+ static void set_dump_histograms_on_exit(bool value) {
+ dump_histograms_on_exit_ = value;
+ }
+
+ static int test_timeout_ms() { return timeout_ms_; }
+ static void set_test_timeout_ms(int value) {
+ timeout_ms_ = value;
+ }
+
+ // Called by some tests that wish to have a base profile to start from. This
+ // "user data directory" (containing one or more profiles) will be recursively
+ // copied into the user data directory for the test and the files will be
+ // evicted from the OS cache. To start with a blank profile, supply an empty
+ // string (the default).
+ std::wstring template_user_data() const { return template_user_data_; }
+ void set_template_user_data(const std::wstring& template_user_data) {
+ template_user_data_ = template_user_data;
+ }
+
+ // Return the user data directory being used by the browser instance in
+ // UITest::SetUp().
+ std::wstring user_data_dir() const { return user_data_dir_; }
+
+ // Count the number of active browser processes. This function only counts
+ // browser processes that share the same profile directory as the current
+ // process. The count includes browser sub-processes.
+ static int GetBrowserProcessCount();
+
+ // Returns a copy of local state preferences. The caller is responsible for
+ // deleting the returned object. Returns NULL if there is an error.
+ DictionaryValue* GetLocalState();
+
+ // Returns a copy of the default profile preferences. The caller is
+ // responsible for deleting the returned object. Returns NULL if there is an
+ // error.
+ DictionaryValue* GetDefaultProfilePreferences();
+
+ private:
+ // Check that no processes related to Chrome exist, displaying
+ // the given message if any do.
+ void AssertAppNotRunning(const std::wstring& error_message);
+
+ protected:
+ AutomationProxy* automation() {
+ EXPECT_TRUE(server_.get());
+ return server_.get();
+ }
+
+ // Wait a certain amount of time for all the app processes to exit,
+ // forcibly killing them if they haven't exited by then.
+ // It has the side-effect of killing every browser window opened in your
+ // session, even those unrelated in the test.
+ void CleanupAppProcesses();
+
+ // Returns the proxy for the currently active tab, or NULL if there is no
+ // tab or there was some kind of error. The returned pointer MUST be
+ // deleted by the caller if non-NULL.
+ TabProxy* GetActiveTab();
+
+ // ********* Member variables *********
+
+ std::wstring browser_directory_; // Path to the browser executable,
+ // with no trailing slash
+ std::wstring test_data_directory_; // Path to the unit test data,
+ // with no trailing slash
+ std::wstring launch_arguments_; // Arguments to the browser on launch.
+ int expected_errors_; // The number of errors expected during
+ // the run (generally 0).
+ int expected_crashes_; // The number of crashes expected during
+ // the run (generally 0).
+ std::wstring homepage_; // Homepage used for testing.
+ bool wait_for_initial_loads_; // Wait for initial loads to complete
+ // in SetUp() before running test body.
+ TimeTicks browser_launch_time_; // Time when the browser was run.
+ bool dom_automation_enabled_; // This can be set to true to have the
+ // test run the dom automation case.
+ std::wstring template_user_data_; // See set_template_user_data().
+ HANDLE process_; // Handle the the first Chrome process.
+ std::wstring user_data_dir_; // User data directory used for the test
+ static bool in_process_renderer_; // true if we're in single process mode
+ bool show_window_; // Determines if the window is shown or
+ // hidden. Defaults to hidden.
+ bool clear_profile_; // If true the profile is cleared before
+ // launching. Default is true.
+ bool include_testing_id_; // Should we supply the testing channel
+ // id on the command line? Default is
+ // true.
+ bool use_existing_browser_; // Duplicate of the static version.
+ // Default value comes from static.
+
+ private:
+ FILETIME test_start_time_; // Time the test was started
+ // (so we can check for new crash dumps)
+ static bool in_process_plugins_;
+ static bool no_sandbox_;
+ static bool safe_plugins_;
+ static bool full_memory_dump_; // If true, write full memory dump
+ // during crash.
+ static bool show_error_dialogs_; // If true, a user is paying attention
+ // to the test, so show error dialogs.
+ static bool default_use_existing_browser_; // The test connects to an already
+ // running browser instance.
+ static bool dump_histograms_on_exit_; // Include histograms in log on exit.
+ static bool enable_dcheck_; // Enable dchecks in release mode.
+ static bool silent_dump_on_dcheck_; // Dump process memory on dcheck without
+ // crashing.
+ static int timeout_ms_; // Timeout in milliseconds to wait
+ // for an test to finish.
+ ::scoped_ptr<AutomationProxy> server_;
+};
+
+// These exist only to support the gTest assertion macros, and
+// shouldn't be used in normal program code.
+#ifdef UNIT_TEST
+std::ostream& operator<<(std::ostream& out, const std::wstring& wstr);
+
+template<typename T>
+std::ostream& operator<<(std::ostream& out, const ::scoped_ptr<T>& ptr) {
+ return out << ptr.get();
+}
+#endif // UNIT_TEST
+
+#endif // CHROME_TEST_UI_UI_TEST_H__
diff --git a/chrome/test/ui/ui_test_suite.cc b/chrome/test/ui/ui_test_suite.cc
new file mode 100644
index 0000000..408330a
--- /dev/null
+++ b/chrome/test/ui/ui_test_suite.cc
@@ -0,0 +1,36 @@
+// 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.
+
+#include "chrome/test/ui/ui_test_suite.h"
+
+// Force a test to use an already running browser instance. UI tests only.
+const wchar_t UITestSuite::kUseExistingBrowser[] = L"use-existing-browser";
+
+// Timeout for the test in milliseconds. UI tests only.
+const wchar_t UITestSuite::kTestTimeout[] = L"test-timeout";
diff --git a/chrome/test/ui/ui_test_suite.h b/chrome/test/ui/ui_test_suite.h
new file mode 100644
index 0000000..7631def
--- /dev/null
+++ b/chrome/test/ui/ui_test_suite.h
@@ -0,0 +1,81 @@
+// 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.
+
+#ifndef CHROME_TEST_UI_UI_TEST_SUITE_H_
+#define CHROME_TEST_UI_UI_TEST_SUITE_H_
+
+#include "chrome/test/ui/ui_test.h"
+#include "chrome/test/unit/chrome_test_suite.h"
+
+class UITestSuite : public ChromeTestSuite {
+ public:
+ UITestSuite(int argc, char** argv) : ChromeTestSuite(argc, argv) {
+ }
+
+ protected:
+
+ virtual void Initialize() {
+ ChromeTestSuite::Initialize();
+
+ UITest::set_in_process_renderer(
+ parsed_command_line_.HasSwitch(switches::kSingleProcess));
+ UITest::set_in_process_plugins(
+ parsed_command_line_.HasSwitch(switches::kInProcessPlugins));
+ UITest::set_no_sandbox(
+ parsed_command_line_.HasSwitch(switches::kNoSandbox));
+ UITest::set_full_memory_dump(
+ parsed_command_line_.HasSwitch(switches::kFullMemoryCrashReport));
+ UITest::set_safe_plugins(
+ parsed_command_line_.HasSwitch(switches::kSafePlugins));
+ UITest::set_use_existing_browser(
+ parsed_command_line_.HasSwitch(UITestSuite::kUseExistingBrowser));
+ UITest::set_dump_histograms_on_exit(
+ parsed_command_line_.HasSwitch(switches::kDumpHistogramsOnExit));
+ UITest::set_enable_dcheck(
+ parsed_command_line_.HasSwitch(switches::kEnableDCHECK));
+ UITest::set_silent_dump_on_dcheck(
+ parsed_command_line_.HasSwitch(switches::kSilentDumpOnDCHECK));
+ std::wstring test_timeout =
+ parsed_command_line_.GetSwitchValue(UITestSuite::kTestTimeout);
+ if (!test_timeout.empty()) {
+ UITest::set_test_timeout_ms(_wtoi(test_timeout.c_str()));
+ }
+ }
+
+ virtual void SuppressErrorDialogs() {
+ TestSuite::SuppressErrorDialogs();
+ UITest::set_show_error_dialogs(false);
+ }
+
+ private:
+ static const wchar_t kUseExistingBrowser[];
+ static const wchar_t kTestTimeout[];
+};
+
+#endif // CHROME_TEST_UI_UI_TEST_SUITE_H_
diff --git a/chrome/test/ui/ui_tests.vcproj b/chrome/test/ui/ui_tests.vcproj
new file mode 100644
index 0000000..4c9ffac
--- /dev/null
+++ b/chrome/test/ui/ui_tests.vcproj
@@ -0,0 +1,528 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="ui_tests"
+ ProjectGUID="{76235B67-1C27-4627-8A33-4B2E1EF93EDE}"
+ RootNamespace="ui_tests"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ ConfigurationType="1"
+ InheritedPropertySheets="$(SolutionDir)..\build\common.vsprops;$(SolutionDir)..\build\debug.vsprops;..\..\tools\build\win\precompiled_wtl.vsprops;$(SolutionDir)..\third_party\libxml\build\using_libxml.vsprops;$(SolutionDir)..\third_party\libxslt\build\using_libxslt.vsprops;..\..\tools\build\win\unit_test.vsprops;..\..\tools\build\win\ui_test.vsprops;..\..\tools\build\win\test_memory_usage.vsprops;$(SolutionDir)..\skia\using_skia.vsprops;$(SolutionDir)..\third_party\icu38\build\using_icu.vsprops;$(SolutionDir)\tools\build\win\js_engine.vsprops;$(SolutionDir)..\testing\using_gtest.vsprops"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="&quot;$(OutDir)\obj\generated_resources&quot;"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="winmm.lib"
+ />
+ <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"
+ ConfigurationType="1"
+ InheritedPropertySheets="$(SolutionDir)..\build\common.vsprops;$(SolutionDir)..\build\release.vsprops;$(SolutionDir)..\third_party\libxml\build\using_libxml.vsprops;$(SolutionDir)..\third_party\libxslt\build\using_libxslt.vsprops;..\..\tools\build\win\unit_test.vsprops;..\..\tools\build\win\ui_test.vsprops;$(SolutionDir)..\skia\using_skia.vsprops;$(SolutionDir)..\third_party\icu38\build\using_icu.vsprops;$(SolutionDir)\tools\build\win\js_engine.vsprops;$(SolutionDir)..\testing\using_gtest.vsprops"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="&quot;$(OutDir)\obj\generated_resources&quot;"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="winmm.lib"
+ />
+ <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="Common"
+ >
+ <File
+ RelativePath="..\..\tools\build\win\precompiled_wtl.cc"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="1"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\tools\build\win\precompiled_wtl.h"
+ >
+ </File>
+ <File
+ RelativePath=".\run_all_unittests.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\test_file_util.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\testing_browser_process.h"
+ >
+ </File>
+ <File
+ RelativePath=".\ui_test.cc"
+ >
+ </File>
+ <File
+ RelativePath=".\ui_test.h"
+ >
+ </File>
+ <File
+ RelativePath=".\ui_test_suite.cc"
+ >
+ </File>
+ <File
+ RelativePath=".\ui_test_suite.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\net\url_request\url_request_test_job.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\net\url_request\url_request_test_job.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="TestChromeMain"
+ >
+ <File
+ RelativePath="..\..\app\chrome_main_uitest.cc"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="TestErrorPage"
+ >
+ <File
+ RelativePath="..\..\browser\errorpage_uitest.cc"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="TestBrowser"
+ >
+ <File
+ RelativePath="..\..\browser\browser_uitest.cc"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="TestChromeLogging"
+ >
+ <File
+ RelativePath="..\..\common\logging_chrome_uitest.cc"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="TestDownload"
+ >
+ <File
+ RelativePath="..\..\browser\download_uitest.cc"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="TestImages"
+ >
+ <File
+ RelativePath="..\..\browser\images_uitest.cc"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="TestIFrame"
+ >
+ <File
+ RelativePath="..\..\browser\iframe_uitest.cc"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="TestCache"
+ >
+ <File
+ RelativePath="..\..\common\net\cache_uitest.cc"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="TestSanity"
+ >
+ <File
+ RelativePath="..\..\browser\sanity_uitest.cc"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="TestAutomationProxy"
+ >
+ <File
+ RelativePath="..\automation\automation_proxy_uitest.cc"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="TestNPAPI"
+ >
+ <File
+ RelativePath=".\layout_plugin_uitest.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\npapi_uitest.cpp"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="TestSessionHistory"
+ >
+ <File
+ RelativePath="..\..\browser\session_history_uitest.cc"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="TestSessionRestore"
+ >
+ <File
+ RelativePath="..\..\browser\session_restore_uitest.cc"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="TestTabRestore"
+ >
+ <File
+ RelativePath="..\..\browser\tab_restore_uitest.cc"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="TestAuthentication"
+ >
+ <File
+ RelativePath="..\..\browser\login_prompt_uitest.cc"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="TestPreferences"
+ >
+ <File
+ RelativePath="..\..\common\pref_service_uitest.cc"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="TestViewSource"
+ >
+ <File
+ RelativePath="..\..\browser\view_source_uitest.cc"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="TestRedirects"
+ >
+ <File
+ RelativePath="..\..\browser\history\redirect_uitest.cc"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="TestResourceDispatcherHost"
+ >
+ <File
+ RelativePath="..\..\browser\resource_dispatcher_host_uitest.cc"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="TestFindInPage"
+ >
+ <File
+ RelativePath="..\..\browser\find_in_page_controller_uitest.cc"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="TestPageLoader"
+ >
+ <File
+ RelativePath="..\perf\mem_usage.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\perf\mem_usage.h"
+ >
+ </File>
+ <File
+ RelativePath="..\reliability\page_load_test.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\reliability\page_load_test.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="TestSandbox"
+ >
+ <File
+ RelativePath=".\sandbox_uitests.cc"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="TestInspector"
+ >
+ <File
+ RelativePath=".\inspector_controller_uitest.cc"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="TestLocalizedBuilds"
+ >
+ <File
+ RelativePath="..\..\browser\locale_tests_uitest.cc"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="TestMetricsService"
+ >
+ <File
+ RelativePath="..\..\browser\metrics_service_uitest.cc"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="TestInterstitialPage"
+ >
+ <File
+ RelativePath="..\..\browser\interstitial_page_uitest.cc"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="TestSSL"
+ >
+ <File
+ RelativePath="..\..\browser\ssl_uitest.cc"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="TestAccessibility"
+ >
+ <File
+ RelativePath="..\accessibility\accessibility_tests.cc"
+ >
+ </File>
+ <Filter
+ Name="Accessibility Client"
+ >
+ <File
+ RelativePath="..\accessibility\accessibility_util.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\accessibility\accessibility_util.h"
+ >
+ </File>
+ <File
+ RelativePath="..\accessibility\browser_impl.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\accessibility\browser_impl.h"
+ >
+ </File>
+ <File
+ RelativePath="..\accessibility\constants.h"
+ >
+ </File>
+ <File
+ RelativePath="..\accessibility\keyboard_util.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\accessibility\keyboard_util.h"
+ >
+ </File>
+ <File
+ RelativePath="..\accessibility\registry_util.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\accessibility\registry_util.h"
+ >
+ </File>
+ <File
+ RelativePath="..\accessibility\tab_impl.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\accessibility\tab_impl.h"
+ >
+ </File>
+ </Filter>
+ </Filter>
+ <Filter
+ Name="TestCrashRecovery"
+ >
+ <File
+ RelativePath="..\..\browser\crash_recovery_uitest.cc"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="TestPrinting"
+ >
+ <File
+ RelativePath="..\..\browser\printing\printing_layout_uitest.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\browser\printing\printing_test.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="TestSavePage"
+ >
+ <File
+ RelativePath="..\..\browser\save_page_uitest.cc"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="TestOmnibox"
+ >
+ <File
+ RelativePath=".\omnibox_uitest.cc"
+ >
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/chrome/test/unit/chrome_test_suite.h b/chrome/test/unit/chrome_test_suite.h
new file mode 100644
index 0000000..1c659f8
--- /dev/null
+++ b/chrome/test/unit/chrome_test_suite.h
@@ -0,0 +1,90 @@
+// 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.
+
+#ifndef CHROME_TEST_UNIT_CHROME_TEST_SUITE_H_
+#define CHROME_TEST_UNIT_CHROME_TEST_SUITE_H_
+
+#include "base/stats_table.h"
+#include "base/file_util.h"
+#include "base/path_service.h"
+#include "base/test_suite.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/common/chrome_paths.h"
+#include "chrome/common/chrome_switches.h"
+#include "chrome/common/resource_bundle.h"
+#include "chrome/test/testing_browser_process.h"
+
+class ChromeTestSuite : public TestSuite {
+public:
+ ChromeTestSuite(int argc, char** argv) : TestSuite(argc, argv) {
+ }
+
+ virtual ~ChromeTestSuite() {
+ ResourceBundle::CleanupSharedInstance();
+
+ delete g_browser_process;
+ g_browser_process = NULL;
+
+ // Tear down shared StatsTable; prevents unit_tests from leaking it.
+ StatsTable::set_current(NULL);
+ delete stats_table_;
+ }
+
+protected:
+
+ virtual void Initialize() {
+ TestSuite::Initialize();
+
+ chrome::RegisterPathProvider();
+ g_browser_process = new TestingBrowserProcess;
+
+ // Notice a user data override, and otherwise default to using a custom
+ // user data directory that lives alongside the current app.
+ // NOTE: The user data directory will be erased before each UI test that
+ // uses it, in order to ensure consistency.
+ std::wstring user_data_dir =
+ parsed_command_line_.GetSwitchValue(switches::kUserDataDir);
+ if (user_data_dir.empty() &&
+ PathService::Get(base::DIR_EXE, &user_data_dir))
+ file_util::AppendToPath(&user_data_dir, L"test_user_data");
+ if (!user_data_dir.empty())
+ PathService::Override(chrome::DIR_USER_DATA, user_data_dir);
+
+ ResourceBundle::InitSharedInstance(std::wstring());
+ ResourceBundle::GetSharedInstance().LoadThemeResources();
+
+ // initialize the global StatsTable for unit_tests
+ stats_table_ = new StatsTable(L"unit_tests", 20, 200);
+ StatsTable::set_current(stats_table_);
+ }
+
+ StatsTable* stats_table_;
+};
+
+#endif // CHROME_TEST_UNIT_CHROME_TEST_SUITE_H_ \ No newline at end of file
diff --git a/chrome/test/unit/run_all_unittests.cc b/chrome/test/unit/run_all_unittests.cc
new file mode 100644
index 0000000..f8d6fea
--- /dev/null
+++ b/chrome/test/unit/run_all_unittests.cc
@@ -0,0 +1,34 @@
+// 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.
+
+#include "chrome/test/unit/chrome_test_suite.h"
+
+int main(int argc, char **argv) {
+ return ChromeTestSuite(argc, argv).Run();
+}
diff --git a/chrome/test/unit/unittests.vcproj b/chrome/test/unit/unittests.vcproj
new file mode 100644
index 0000000..dfea76e
--- /dev/null
+++ b/chrome/test/unit/unittests.vcproj
@@ -0,0 +1,924 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="unit_tests"
+ ProjectGUID="{ECFC2BEC-9FC0-4AD9-9649-5F26793F65FC}"
+ RootNamespace="unit_tests"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ ConfigurationType="1"
+ InheritedPropertySheets="$(SolutionDir)..\build\common.vsprops;$(SolutionDir)..\build\debug.vsprops;..\..\tools\build\win\precompiled_wtl.vsprops;..\..\tools\build\win\unit_test.vsprops;$(SolutionDir)..\third_party\libpng\using_libpng.vsprops;$(SolutionDir)..\third_party\zlib\using_zlib.vsprops;$(SolutionDir)..\skia\using_skia.vsprops;$(SolutionDir)..\third_party\libxml\build\using_libxml.vsprops;..\..\..\third_party\icu38\build\using_icu.vsprops;$(SolutionDir)..\testing\using_gtest.vsprops;..\..\third_party\hunspell\using_hunspell.vsprops"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ AdditionalIncludeDirectories="$(SolutionDir)..;&quot;$(IntDir)&quot;;&quot;$(IntDir)&quot;;&quot;$(SolutionDir)&quot;;&quot;$(IntDir)\..\&quot;"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="winmm.lib"
+ />
+ <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"
+ ConfigurationType="1"
+ InheritedPropertySheets="$(SolutionDir)..\build\common.vsprops;$(SolutionDir)..\build\release.vsprops;..\..\tools\build\win\unit_test.vsprops;$(SolutionDir)..\third_party\libpng\using_libpng.vsprops;$(SolutionDir)..\third_party\zlib\using_zlib.vsprops;$(SolutionDir)..\skia\using_skia.vsprops;$(SolutionDir)..\third_party\libxml\build\using_libxml.vsprops;..\..\..\third_party\icu38\build\using_icu.vsprops;$(SolutionDir)..\testing\using_gtest.vsprops;..\..\third_party\hunspell\using_hunspell.vsprops"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ AdditionalIncludeDirectories="$(SolutionDir)..;&quot;$(IntDir)&quot;;&quot;$(IntDir)&quot;;&quot;$(SolutionDir)&quot;;&quot;$(IntDir)\..\&quot;"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="winmm.lib"
+ />
+ <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="Common"
+ >
+ <File
+ RelativePath="..\..\browser\browser_resources.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\browser\browser_resources.rc"
+ >
+ </File>
+ <File
+ RelativePath=".\chrome_test_suite.h"
+ >
+ </File>
+ <File
+ RelativePath=".\multiprocess_test.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\tools\build\win\precompiled_wtl.cc"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="1"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\tools\build\win\precompiled_wtl.h"
+ >
+ </File>
+ <File
+ RelativePath=".\run_all_unittests.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\testing_browser_process.h"
+ >
+ </File>
+ <File
+ RelativePath="..\testing_profile.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\testing_profile.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\net\url_request\url_request_test_job.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\net\url_request\url_request_test_job.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="TestGoogleURLTracker"
+ >
+ <File
+ RelativePath="..\..\browser\google_url_tracker_unittest.cc"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="TestURLFetcher"
+ >
+ <File
+ RelativePath="..\..\browser\url_fetcher_unittest.cc"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="TestURLFixerUpper"
+ >
+ <File
+ RelativePath="..\..\browser\url_fixer_upper_unittest.cc"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="TestWebContents"
+ >
+ <File
+ RelativePath="..\..\browser\web_contents_unittest.cc"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="TestVisitedLink"
+ >
+ <File
+ RelativePath="..\..\browser\visitedlink_unittest.cc"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="TestResourceDispatcher"
+ >
+ <File
+ RelativePath="..\..\browser\resource_dispatcher_host_unittest.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\common\resource_dispatcher_unittest.cc"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="TestIPCMessage"
+ >
+ <File
+ RelativePath="..\..\common\ipc_message_unittest.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\common\ipc_sync_channel_unittest.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\common\ipc_sync_channel_unittest.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\common\ipc_sync_message_unittest.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\common\ipc_sync_message_unittest.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="TestController"
+ >
+ <File
+ RelativePath="..\..\browser\controller_unittest.cc"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="TestAutocomplete"
+ >
+ <File
+ RelativePath="..\..\browser\autocomplete\autocomplete_unittest.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\browser\autocomplete\history_contents_provider_unittest.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\browser\autocomplete\history_url_provider_unittest.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\browser\autocomplete\keyword_provider_unittest.cc"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="TestChromeViews"
+ >
+ <File
+ RelativePath="..\..\views\focus_manager_unittest.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\views\grid_layout_unittest.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\views\view_unittest.cc"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="TestHistory"
+ >
+ <File
+ RelativePath="..\..\browser\history\expire_history_backend_unittest.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\browser\history\history_backend_unittest.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\browser\history\history_querying_unittest.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\browser\history\history_types_unittest.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\browser\history\history_unittest.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\browser\history\starred_url_database_unittest.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\browser\history\text_database_manager_unittest.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\browser\history\text_database_unittest.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\browser\history\url_database_unittest.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\browser\history\visit_database_unittest.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\browser\history\visit_tracker_unittest.cc"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="TestJSONValueSerializer"
+ >
+ <File
+ RelativePath="..\..\common\json_value_serializer_unittest.cc"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="TestNotificationService"
+ >
+ <File
+ RelativePath="..\..\common\notification_service_unittest.cc"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="TestAnimation"
+ >
+ <File
+ RelativePath="..\..\common\animation_unittest.cc"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="TestJPEGCodec"
+ >
+ <File
+ RelativePath="..\..\common\jpeg_codec_unittest.cc"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="TestPrefService"
+ >
+ <File
+ RelativePath="..\..\common\pref_member_unittest.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\common\pref_service_unittest.cc"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="TestSessionService"
+ >
+ <File
+ RelativePath="..\..\browser\session_backend_unittest.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\browser\session_service_test_helper.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\browser\session_service_test_helper.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\browser\session_service_unittest.cc"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="TestThumbnailDatabase"
+ >
+ <File
+ RelativePath="..\..\browser\history\thumbnail_database_unittest.cc"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="TestL10n"
+ >
+ <File
+ RelativePath="..\..\common\l10n_util_unittest.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\data\resource.h"
+ >
+ </File>
+ <File
+ RelativePath="..\data\resource.rc"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="TestMRUCache"
+ >
+ <File
+ RelativePath="..\..\common\mru_cache_unittest.cc"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="TestPerformanceProfiler"
+ >
+ <File
+ RelativePath="..\..\browser\navigation_profiler_unittest.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\browser\page_load_tracker_unittest.cc"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="TestNavigationController"
+ >
+ <File
+ RelativePath="..\..\browser\navigation_controller_unittest.cc"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="TestMetricsLog"
+ >
+ <File
+ RelativePath="..\..\browser\metrics_log_unittest.cc"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="TestBzip2"
+ >
+ <File
+ RelativePath="..\..\common\bzip2_unittest.cc"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="TestTitleChomper"
+ >
+ <File
+ RelativePath="..\..\browser\title_chomper_unittest.cc"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="TestTemplateURLParser"
+ >
+ <File
+ RelativePath="..\..\browser\template_url_parser_unittest.cc"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="TestTemplateURL"
+ >
+ <File
+ RelativePath="..\..\browser\template_url_unittest.cc"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="TestTemplateURLModel"
+ >
+ <File
+ RelativePath="..\..\browser\template_url_model_unittest.cc"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="TestBookmarkDragData"
+ >
+ <File
+ RelativePath="..\..\browser\bookmark_drag_data_unittest.cc"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="TestMetricsResponse"
+ >
+ <File
+ RelativePath="..\..\browser\metrics_response_unittest.cc"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="TestProfileManager"
+ >
+ <File
+ RelativePath="..\..\browser\profile_manager_unittest.cc"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="TestQueryParser"
+ >
+ <File
+ RelativePath="..\..\browser\history\query_parser_unittest.cc"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="TestWinUtil"
+ >
+ <File
+ RelativePath="..\..\common\win_util_unittest.cc"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="TestTimeFormat"
+ >
+ <File
+ RelativePath="..\..\common\time_format_unittest.cc"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="TestBackForwardHistory"
+ >
+ <File
+ RelativePath="..\..\browser\back_forward_menu_model_unittest.cc"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="TestBookmarkBarModel"
+ >
+ <File
+ RelativePath="..\..\browser\bookmark_bar_model_unittest.cc"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="TestCacheManagerHost"
+ >
+ <File
+ RelativePath="..\..\browser\cache_manager_host_unittest.cc"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="TestFocusManager"
+ >
+ <File
+ RelativePath="..\..\views\focus_manager_unittest.cc"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="TestDragAndDrop"
+ >
+ <File
+ RelativePath="..\..\common\os_exchange_data_unittest.cc"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="TestSnippet"
+ >
+ <File
+ RelativePath="..\..\browser\history\snippet_unittest.cc"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="TestEmf"
+ >
+ <File
+ RelativePath="..\..\common\gfx\emf_unittest.cc"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="TestEncryptor"
+ >
+ <File
+ RelativePath="..\..\browser\encryptor_unittest.cc"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="TestSpellCheck"
+ >
+ <File
+ RelativePath="..\..\renderer\spellcheck_unittest.cc"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="TestDownload"
+ >
+ <File
+ RelativePath="..\..\browser\download_manager_unittest.cc"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="TestTabStripModel"
+ >
+ <File
+ RelativePath="..\..\browser\tabs\tab_strip_model_unittest.cc"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="TestIconUtil"
+ >
+ <File
+ RelativePath="..\..\common\gfx\icon_util_unittest.cc"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="TestWindowSizer"
+ >
+ <File
+ RelativePath="..\..\browser\window_sizer_unittest.cc"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="TestURLElider"
+ >
+ <File
+ RelativePath="..\..\common\gfx\url_elider_unittest.cc"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="TestPrinting"
+ >
+ <File
+ RelativePath="..\..\browser\printing\page_setup_unittest.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\browser\printing\printing_test.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\browser\printing\win_printing_context_unittest.cc"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="TestSafeBrowsing"
+ >
+ <File
+ RelativePath="..\..\browser\safe_browsing\bloom_filter_unittest.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\browser\safe_browsing\chunk_range_unittest.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\browser\safe_browsing\protocol_manager_unittest.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\browser\safe_browsing\protocol_parser_unittest.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\browser\safe_browsing\safe_browsing_database_unittest.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\browser\safe_browsing\safe_browsing_util_unittest.cc"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="TestChromePlugin"
+ >
+ <File
+ RelativePath="..\..\common\chrome_plugin_unittest.cc"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="TestSiteInstance"
+ >
+ <File
+ RelativePath="..\..\browser\site_instance_unittest.cc"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="TestSavePage"
+ >
+ <File
+ RelativePath="..\..\browser\save_package_unittest.cc"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="TestPasswordManager"
+ >
+ <File
+ RelativePath="..\..\browser\password_form_manager_unittest.cc"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="TestRendererSecurityPolicy"
+ >
+ <File
+ RelativePath="..\..\browser\renderer_security_policy_unittest.cc"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="TestDnsHostInfo"
+ >
+ <File
+ RelativePath="..\..\browser\net\dns_host_info_unittest.cc"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="TestDnsPrefetch"
+ >
+ <File
+ RelativePath="..\..\browser\net\dns_master_unittest.cc"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="TestRenderDnsMaster"
+ >
+ <File
+ RelativePath="..\..\renderer\net\render_dns_master_unittest.cc"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="TestRenderDnsQueue"
+ >
+ <File
+ RelativePath="..\..\renderer\net\render_dns_queue_unittest.cc"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="TestImporter"
+ >
+ <File
+ RelativePath="..\..\browser\firefox_importer_unittest.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\browser\importer_unittest.cc"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="TestRLZ"
+ >
+ <File
+ RelativePath="..\..\browser\rlz\rlz_unittest.cc"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="TestWebDatabase"
+ >
+ <File
+ RelativePath="..\..\browser\webdata\web_database_unittest.cc"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="TestChromeThread"
+ >
+ <File
+ RelativePath="..\..\browser\chrome_thread_unittest.cc"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="TestHunspell"
+ >
+ <File
+ RelativePath="..\..\tools\convert_dict\aff_reader.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\tools\convert_dict\aff_reader.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\third_party\hunspell\google\bdict.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\third_party\hunspell\google\bdict_reader.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\third_party\hunspell\google\bdict_reader.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\third_party\hunspell\google\bdict_writer.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\third_party\hunspell\google\bdict_writer.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\tools\convert_dict\dic_reader.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\tools\convert_dict\dic_reader.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\tools\convert_dict\hunspell_reader.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\tools\convert_dict\hunspell_reader.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\third_party\hunspell\google\hunspell_tests.cc"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="TestURL"
+ >
+ <File
+ RelativePath="..\..\..\googleurl\src\gurl_unittest.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\googleurl\src\url_canon_unittest.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\googleurl\src\url_parse_unittest.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\googleurl\src\url_util_unittest.cc"
+ >
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/chrome/test/unit/win/rundebug.bat b/chrome/test/unit/win/rundebug.bat
new file mode 100644
index 0000000..0b8c4bc
--- /dev/null
+++ b/chrome/test/unit/win/rundebug.bat
@@ -0,0 +1,5 @@
+rem This is a convenience batch file that you can use to run the debug-mode
+rem unit tests via a Windows shortcut.
+
+..\..\..\debug\UnitTests.exe
+pause