diff --git a/chrome/browser/extensions/user_script_master.cc b/chrome/browser/extensions/user_script_master.cc
index b0552e0fba49968356cda85da9efdeef9bbde52e..69fd746ddbd9999ba88d8a447b28f4e8f4201b7d 100644
--- a/chrome/browser/extensions/user_script_master.cc
+++ b/chrome/browser/extensions/user_script_master.cc
@@ -166,6 +166,11 @@ void UserScriptMaster::ScriptReloader::LoadScriptsFromDirectory(
          file = enumerator.Next()) {
       result->push_back(UserScript());
       UserScript& user_script = result->back();
+
+      // We default standalone user scripts to document-end for better
+      // Greasemonkey compatibility.
+      user_script.set_run_location(UserScript::DOCUMENT_END);
+
       // Push single js file in this UserScript.
       GURL url(std::string(chrome::kUserScriptScheme) + ":/" +
           net::FilePathToFileURL(file).ExtractFileName());
diff --git a/chrome/chrome.gyp b/chrome/chrome.gyp
index eaec76b60015cfaf2b8d6f042f42c81c9cf77ae3..59946bb9f28670e826262009ee5bf0760cc12219 100755
--- a/chrome/chrome.gyp
+++ b/chrome/chrome.gyp
@@ -3302,6 +3302,8 @@
         'renderer/renderer_web_database_observer.h',
         'renderer/socket_stream_dispatcher.cc',
         'renderer/socket_stream_dispatcher.h',
+        'renderer/user_script_idle_scheduler.cc',
+        'renderer/user_script_idle_scheduler.h',
         'renderer/user_script_slave.cc',
         'renderer/user_script_slave.h',
         'renderer/visitedlink_slave.cc',
diff --git a/chrome/common/extensions/docs/content_scripts.html b/chrome/common/extensions/docs/content_scripts.html
index 51beb4d5aaa4f0f109a4cf66ce2878f200993c4d..feba6ba489b9a7639ce8763a3679ab4ecab1d970 100644
--- a/chrome/common/extensions/docs/content_scripts.html
+++ b/chrome/common/extensions/docs/content_scripts.html
@@ -346,7 +346,24 @@ learn about the
   <tr>
     <td>run_at</td>
     <td>string</td>
-    <td>Optional. Controls when the files in <code>js</code> are injected. Can be <code>"document_start"</code> or <code>"document_end"</code>. Defaults to <code>"document_end"</code>. In the case of <code>"document_start"</code>, the files are injected after any files from <code>"css"</code>, but before any other DOM is constructed or any other script is run. In the case of <code>"document_end"</code>, the files are injected after the DOM is complete, but before subresources like images and frames have necessarily loaded.</td>
+    <td>Optional. Controls when the files in <code>js</code> are injected. Can be <code>"document_start"</code>, <code>"document_end"</code>, or <code>"document_idle"</code>. Defaults to <code>"document_idle"</code>.
+    
+    <br><br>
+    
+    In the case of <code>"document_start"</code>, the files are injected after any files from <code>"css"</code>, but before any other DOM is constructed or any other script is run.
+    
+    <br><br>
+    
+    In the case of <code>"document_end"</code>, the files are injected immediately after the DOM is complete, but before subresources like images and frames have loaded.
+    
+    <br><br>
+    
+    In the case of <code>"document_idle"</code>, the browser chooses a time to inject scripts between <code>"document_end"</code> and immediately after the <code><a href="http://www.whatwg.org/specs/web-apps/current-work/#handler-onload">window.onload</a></code> event fires. The exact moment of injection depends on how complex the document is and how long it is taking to load, and is optimized for page load speed.
+    
+    <br><br>
+    
+    <b>NOTE:</b> In <code>document_idle</code>, content scripts may not necessarily receive the window.onload event, because they may run after it has
+    already fired. In most cases, listening for the onload event is unnecessary for content scripts running at <code>document_idle</code> because they are guaranteed to run after the DOM is complete. If your script definitely needs to run after <code>window.onload</code> you can check if it has already fired by using the <code><a href="http://www.whatwg.org/specs/web-apps/current-work/#dom-document-readystate">document.readyState</a></code> property.</td>
   </tr>
 </tbody></table>
 
diff --git a/chrome/common/extensions/docs/static/content_scripts.html b/chrome/common/extensions/docs/static/content_scripts.html
index cbd738f3ae5fe23afc471007a802d77125e79cde..9f1edf18af2fab383c6a331a15359ea94ba3d250 100644
--- a/chrome/common/extensions/docs/static/content_scripts.html
+++ b/chrome/common/extensions/docs/static/content_scripts.html
@@ -104,7 +104,24 @@ learn about the
   <tr>
     <td>run_at</td>
     <td>string</td>
-    <td>Optional. Controls when the files in <code>js</code> are injected. Can be <code>"document_start"</code> or <code>"document_end"</code>. Defaults to <code>"document_end"</code>. In the case of <code>"document_start"</code>, the files are injected after any files from <code>"css"</code>, but before any other DOM is constructed or any other script is run. In the case of <code>"document_end"</code>, the files are injected after the DOM is complete, but before subresources like images and frames have necessarily loaded.</td>
+    <td>Optional. Controls when the files in <code>js</code> are injected. Can be <code>"document_start"</code>, <code>"document_end"</code>, or <code>"document_idle"</code>. Defaults to <code>"document_idle"</code>.
+    
+    <br><br>
+    
+    In the case of <code>"document_start"</code>, the files are injected after any files from <code>"css"</code>, but before any other DOM is constructed or any other script is run.
+    
+    <br><br>
+    
+    In the case of <code>"document_end"</code>, the files are injected immediately after the DOM is complete, but before subresources like images and frames have loaded.
+    
+    <br><br>
+    
+    In the case of <code>"document_idle"</code>, the browser chooses a time to inject scripts between <code>"document_end"</code> and immediately after the <code><a href="http://www.whatwg.org/specs/web-apps/current-work/#handler-onload">window.onload</a></code> event fires. The exact moment of injection depends on how complex the document is and how long it is taking to load, and is optimized for page load speed.
+    
+    <br><br>
+    
+    <b>NOTE:</b> In <code>document_idle</code>, content scripts may not necessarily receive the window.onload event, because they may run after it has
+    already fired. In most cases, listening for the onload event is unnecessary for content scripts running at <code>document_idle</code> because they are guaranteed to run after the DOM is complete. If your script definitely needs to run after <code>window.onload</code> you can check if it has already fired by using the <code><a href="http://www.whatwg.org/specs/web-apps/current-work/#dom-document-readystate">document.readyState</a></code> property.</td>
   </tr>
 </table>
 
diff --git a/chrome/common/extensions/extension.cc b/chrome/common/extensions/extension.cc
index 429dfb5ea9e8dd38c0e4bbb360d7d435374475ee..c6172321800fedc4a807fbb9957394f9591cb0b3 100644
--- a/chrome/common/extensions/extension.cc
+++ b/chrome/common/extensions/extension.cc
@@ -208,6 +208,8 @@ bool Extension::LoadUserScriptHelper(const DictionaryValue* content_script,
       result->set_run_location(UserScript::DOCUMENT_START);
     } else if (run_location == values::kRunAtDocumentEnd) {
       result->set_run_location(UserScript::DOCUMENT_END);
+    } else if (run_location == values::kRunAtDocumentIdle) {
+      result->set_run_location(UserScript::DOCUMENT_IDLE);
     } else {
       *error = ExtensionErrorUtils::FormatErrorMessage(errors::kInvalidRunAt,
           IntToString(definition_index));
diff --git a/chrome/common/extensions/extension_constants.cc b/chrome/common/extensions/extension_constants.cc
index 8259009f54f8e876f0531eba7a95194ce33031bb..59e7c1492ebaf5a58aae6bec31ce0063075cccb4 100644
--- a/chrome/common/extensions/extension_constants.cc
+++ b/chrome/common/extensions/extension_constants.cc
@@ -52,6 +52,7 @@ const wchar_t* kOptionsPage = L"options_page";
 namespace extension_manifest_values {
 const char* kRunAtDocumentStart = "document_start";
 const char* kRunAtDocumentEnd = "document_end";
+const char* kRunAtDocumentIdle = "document_idle";
 const char* kPageActionTypeTab = "tab";
 const char* kPageActionTypePermanent = "permanent";
 }  // namespace extension_manifest_values
diff --git a/chrome/common/extensions/extension_constants.h b/chrome/common/extensions/extension_constants.h
index 7f44bf6661a5588e4d16bcaf32a61fc4abab011a..b7826a79cbf662e3934480f47bb51ff4321fc1be 100644
--- a/chrome/common/extensions/extension_constants.h
+++ b/chrome/common/extensions/extension_constants.h
@@ -54,6 +54,7 @@ namespace extension_manifest_keys {
 namespace extension_manifest_values {
   extern const char* kRunAtDocumentStart;
   extern const char* kRunAtDocumentEnd;
+  extern const char* kRunAtDocumentIdle;
   extern const char* kPageActionTypeTab;
   extern const char* kPageActionTypePermanent;
 }  // namespace extension_manifest_values
diff --git a/chrome/common/extensions/user_script.h b/chrome/common/extensions/user_script.h
index 28b3aaec1928117c1bcda7f21f49eb41a688ddf0..bdd1e5435fdd7f201eee32617192cf5195af2c22 100644
--- a/chrome/common/extensions/user_script.h
+++ b/chrome/common/extensions/user_script.h
@@ -28,6 +28,10 @@ class UserScript {
                      // anything else happens.
     DOCUMENT_END,  // After the entire document is parsed. Same as
                    // DOMContentLoaded.
+    DOCUMENT_IDLE,  // Sometime after DOMContentLoaded, as soon as the document
+                    // is "idle". Currently this uses the simple heuristic of:
+                    // min(DOM_CONTENT_LOADED + TIMEOUT, ONLOAD), but no
+                    // particular injection point is guaranteed.
 
     RUN_LOCATION_LAST  // Leave this as the last item.
   };
@@ -88,9 +92,10 @@ class UserScript {
 
   typedef std::vector<File> FileList;
 
-  // Constructor. Default the run location to document end, which is like
-  // Greasemonkey and probably more useful for typical scripts.
-  UserScript() : run_location_(DOCUMENT_END) {}
+  // Constructor. Default the run location to document idle, which is similar
+  // to Greasemonkey but should result in better page load times for fast-
+  // loading pages.
+  UserScript() : run_location_(DOCUMENT_IDLE) {}
 
   // The place in the document to run the script.
   RunLocation run_location() const { return run_location_; }
diff --git a/chrome/common/extensions/user_script_unittest.cc b/chrome/common/extensions/user_script_unittest.cc
index b171f4e13dbaa2d6e67e9196557c74af0bf03a4a..58ef77e4c490737dda62527e3c92a127caf3a3a7 100644
--- a/chrome/common/extensions/user_script_unittest.cc
+++ b/chrome/common/extensions/user_script_unittest.cc
@@ -122,5 +122,5 @@ TEST(UserScriptTest, Pickle) {
 
 TEST(UserScriptTest, Defaults) {
   UserScript script;
-  ASSERT_EQ(UserScript::DOCUMENT_END, script.run_location());
+  ASSERT_EQ(UserScript::DOCUMENT_IDLE, script.run_location());
 }
diff --git a/chrome/renderer/navigation_state.h b/chrome/renderer/navigation_state.h
index 46031ddd1bedba54a58bb0092beb9201b58a20e4..394aee9e995b69dc3de43d18a947e80c3a912da2 100644
--- a/chrome/renderer/navigation_state.h
+++ b/chrome/renderer/navigation_state.h
@@ -8,6 +8,7 @@
 #include "base/scoped_ptr.h"
 #include "base/time.h"
 #include "chrome/common/page_transition_types.h"
+#include "chrome/renderer/user_script_idle_scheduler.h"
 #include "webkit/api/public/WebDataSource.h"
 #include "webkit/glue/alt_error_page_resource_fetcher.h"
 #include "webkit/glue/password_form.h"
@@ -33,6 +34,13 @@ class NavigationState : public WebKit::WebDataSource::ExtraData {
     return static_cast<NavigationState*>(ds->extraData());
   }
 
+  UserScriptIdleScheduler* user_script_idle_scheduler() {
+    return user_script_idle_scheduler_.get();
+  }
+  void set_user_script_idle_scheduler(UserScriptIdleScheduler* scheduler) {
+    user_script_idle_scheduler_.reset(scheduler);
+  }
+
   // Contains the page_id for this navigation or -1 if there is none yet.
   int32 pending_page_id() const { return pending_page_id_; }
 
@@ -173,7 +181,8 @@ class NavigationState : public WebKit::WebDataSource::ExtraData {
         request_committed_(false),
         is_content_initiated_(is_content_initiated),
         pending_page_id_(pending_page_id),
-        postpone_loading_data_(false) {
+        postpone_loading_data_(false),
+        user_script_idle_scheduler_(NULL) {
   }
 
   PageTransition::Type transition_type_;
@@ -195,6 +204,7 @@ class NavigationState : public WebKit::WebDataSource::ExtraData {
   std::string security_info_;
   bool postpone_loading_data_;
   std::string postponed_data_;
+  scoped_ptr<UserScriptIdleScheduler> user_script_idle_scheduler_;
 
   DISALLOW_COPY_AND_ASSIGN(NavigationState);
 };
diff --git a/chrome/renderer/render_view.cc b/chrome/renderer/render_view.cc
index 95f5e349f54cf623dfb79f211f335cc3d51b2af3..ce8a521e7ab0152c8383d4f28b42dcee35d89fda 100644
--- a/chrome/renderer/render_view.cc
+++ b/chrome/renderer/render_view.cc
@@ -1829,6 +1829,10 @@ void RenderView::willClose(WebFrame* frame) {
     if (url.SchemeIs("http") || url.SchemeIs("https"))
       DumpLoadHistograms();
   }
+
+  WebDataSource* ds = frame->dataSource();
+  NavigationState* navigation_state = NavigationState::FromDataSource(ds);
+  navigation_state->user_script_idle_scheduler()->Cancel();
 }
 
 void RenderView::loadURLExternally(
@@ -2031,11 +2035,13 @@ void RenderView::didCompleteClientRedirect(
 void RenderView::didCreateDataSource(WebFrame* frame, WebDataSource* ds) {
   // The rest of RenderView assumes that a WebDataSource will always have a
   // non-null NavigationState.
-  if (pending_navigation_state_.get()) {
-    ds->setExtraData(pending_navigation_state_.release());
-  } else {
-    ds->setExtraData(NavigationState::CreateContentInitiated());
-  }
+  NavigationState* state = pending_navigation_state_.get() ?
+      pending_navigation_state_.release() : 
+      NavigationState::CreateContentInitiated();
+
+  state->set_user_script_idle_scheduler(
+      new UserScriptIdleScheduler(this, frame));
+  ds->setExtraData(state);
 }
 
 void RenderView::didStartProvisionalLoad(WebFrame* frame) {
@@ -2250,14 +2256,6 @@ void RenderView::didCreateDocumentElement(WebFrame* frame) {
     ExtensionProcessBindings::SetViewType(webview(), view_type_);
   }
 
-  while (!pending_code_execution_queue_.empty()) {
-    scoped_refptr<CodeExecutionInfo> info =
-        pending_code_execution_queue_.front();
-    OnExecuteCode(info->request_id, info->extension_id, info->is_js_code,
-                  info->code_string);
-    pending_code_execution_queue_.pop();
-  }
-
   // Notify the browser about non-blank documents loading in the top frame.
   GURL url = frame->url();
   if (url.is_valid() && url.spec() != chrome::kAboutBlankURL) {
@@ -2292,6 +2290,26 @@ void RenderView::didFinishDocumentLoad(WebFrame* frame) {
     RenderThread::current()->user_script_slave()->InjectScripts(
         frame, UserScript::DOCUMENT_END);
   }
+
+  navigation_state->user_script_idle_scheduler()->DidFinishDocumentLoad();
+}
+
+void RenderView::OnUserScriptIdleTriggered(WebFrame* frame) {
+  if (RenderThread::current()) {  // Will be NULL during unit tests.
+    RenderThread::current()->user_script_slave()->InjectScripts(
+        frame, UserScript::DOCUMENT_IDLE);
+  }
+
+  WebFrame* main_frame = webview()->mainFrame();
+  if (frame == main_frame) {
+    while (!pending_code_execution_queue_.empty()) {
+      scoped_refptr<CodeExecutionInfo> info =
+          pending_code_execution_queue_.front();
+      ExecuteCodeImpl(main_frame, info->request_id, info->extension_id,
+                      info->is_js_code, info->code_string);
+      pending_code_execution_queue_.pop();
+    }
+  }
 }
 
 void RenderView::didHandleOnloadEvents(WebFrame* frame) {
@@ -2307,6 +2325,7 @@ void RenderView::didFinishLoad(WebFrame* frame) {
   NavigationState* navigation_state = NavigationState::FromDataSource(ds);
   DCHECK(navigation_state);
   navigation_state->set_finish_load_time(Time::Now());
+  navigation_state->user_script_idle_scheduler()->DidFinishLoad();
 }
 
 void RenderView::didChangeLocationWithinPage(
@@ -3662,28 +3681,40 @@ void RenderView::OnSetEditCommandsForNextKeyEvent(
 void RenderView::OnExecuteCode(int request_id, const std::string& extension_id,
                                bool is_js_code,
                                const std::string& code_string) {
-  if (is_loading_) {
-    scoped_refptr<CodeExecutionInfo> info = new CodeExecutionInfo(
-        request_id, extension_id, is_js_code, code_string);
-    pending_code_execution_queue_.push(info);
-    return;
-  }
   WebFrame* main_frame = webview() ? webview()->mainFrame() : NULL;
   if (!main_frame) {
     Send(new ViewMsg_ExecuteCodeFinished(routing_id_, request_id, false));
     return;
   }
 
+  WebDataSource* ds = main_frame->dataSource();
+  NavigationState* navigation_state = NavigationState::FromDataSource(ds);
+  if (!navigation_state->user_script_idle_scheduler()->has_run()) {
+    scoped_refptr<CodeExecutionInfo> info = new CodeExecutionInfo(
+        request_id, extension_id, is_js_code, code_string);
+    pending_code_execution_queue_.push(info);
+    return;
+  }
+
+  ExecuteCodeImpl(main_frame, request_id, extension_id, is_js_code,
+                  code_string);
+}
+
+void RenderView::ExecuteCodeImpl(WebFrame* frame,
+                                 int request_id,
+                                 const std::string& extension_id,
+                                 bool is_js_code,
+                                 const std::string& code_string) {
   if (is_js_code) {
     std::vector<WebScriptSource> sources;
     sources.push_back(
         WebScriptSource(WebString::fromUTF8(code_string)));
     UserScriptSlave::InsertInitExtensionCode(&sources, extension_id);
-    main_frame->executeScriptInIsolatedWorld(
+    frame->executeScriptInIsolatedWorld(
         UserScriptSlave::GetIsolatedWorldId(extension_id),
         &sources.front(), sources.size(), EXTENSION_GROUP_CONTENT_SCRIPTS);
   } else {
-    main_frame->insertStyleText(WebString::fromUTF8(code_string), WebString());
+    frame->insertStyleText(WebString::fromUTF8(code_string), WebString());
   }
 
   Send(new ViewMsg_ExecuteCodeFinished(routing_id_, request_id, true));
diff --git a/chrome/renderer/render_view.h b/chrome/renderer/render_view.h
index 900cb2c5603e1c97b0e51df5bfce3d5cb556734e..814d8bd45faf269b1ba766fa419cc30edec7b8f0 100644
--- a/chrome/renderer/render_view.h
+++ b/chrome/renderer/render_view.h
@@ -435,6 +435,10 @@ class RenderView : public RenderWidget,
   // Sends a message and runs a nested message loop.
   bool SendAndRunNestedMessageLoop(IPC::SyncMessage* message);
 
+  // Called when the "idle" user script state has been reached. See
+  // UserScript::DOCUMENT_IDLE.
+  void OnUserScriptIdleTriggered(WebKit::WebFrame* frame);
+
  protected:
   // RenderWidget overrides:
   virtual void Close();
@@ -620,6 +624,11 @@ class RenderView : public RenderWidget,
                      const std::string& extension_id,
                      bool is_js_code,
                      const std::string& code_string);
+  void ExecuteCodeImpl(WebKit::WebFrame* frame,
+                       int request_id,
+                       const std::string& extension_id,
+                       bool is_js_code,
+                       const std::string& code_string);
   void OnUpdateBackForwardListCount(int back_list_count,
                                     int forward_list_count);
   void OnGetAccessibilityInfo(
diff --git a/chrome/renderer/user_script_idle_scheduler.cc b/chrome/renderer/user_script_idle_scheduler.cc
new file mode 100644
index 0000000000000000000000000000000000000000..2468bf13e4ded8254c356ba828c21fdef2ac788a
--- /dev/null
+++ b/chrome/renderer/user_script_idle_scheduler.cc
@@ -0,0 +1,47 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/renderer/user_script_idle_scheduler.h"
+
+#include "base/message_loop.h"
+#include "chrome/renderer/render_view.h"
+
+namespace {
+// The length of time to wait after the DOM is complete to try and run user
+// scripts.
+const int kUserScriptIdleTimeoutMs = 200;
+}
+
+UserScriptIdleScheduler::UserScriptIdleScheduler(RenderView* view,
+                                                 WebKit::WebFrame* frame)
+    : ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)), view_(view),
+  frame_(frame), has_run_(false) {
+}
+
+void UserScriptIdleScheduler::DidFinishDocumentLoad() {
+  MessageLoop::current()->PostDelayedTask(FROM_HERE,
+      method_factory_.NewRunnableMethod(&UserScriptIdleScheduler::MaybeRun),
+      kUserScriptIdleTimeoutMs);
+}
+
+void UserScriptIdleScheduler::DidFinishLoad() {
+  // Ensure that running scripts does not keep any progress UI running.
+  MessageLoop::current()->PostTask(FROM_HERE,
+      method_factory_.NewRunnableMethod(&UserScriptIdleScheduler::MaybeRun));
+}
+
+void UserScriptIdleScheduler::Cancel() {
+  view_ = NULL;
+  frame_ = NULL;
+}
+
+void UserScriptIdleScheduler::MaybeRun() {
+  if (!view_)
+    return;
+
+  DCHECK(frame_);
+  view_->OnUserScriptIdleTriggered(frame_);
+  Cancel();
+  has_run_ = true;
+}
diff --git a/chrome/renderer/user_script_idle_scheduler.h b/chrome/renderer/user_script_idle_scheduler.h
new file mode 100644
index 0000000000000000000000000000000000000000..772d6526ecb1768516bfa3460b904b7f42ef5729
--- /dev/null
+++ b/chrome/renderer/user_script_idle_scheduler.h
@@ -0,0 +1,58 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_RENDERER_USER_SCRIPT_IDLE_SCHEDULER_H_
+#define CHROME_RENDERER_USER_SCRIPT_IDLE_SCHEDULER_H_
+
+#include "base/task.h"
+
+class RenderView;
+
+namespace WebKit {
+class WebFrame;
+}
+
+// Implements support for injecting scripts at "document idle". Currently,
+// determining idleness is simple: it is whichever of the following happens
+// first:
+//
+// a) When the initial DOM for a page is complete + kUserScriptIdleTimeout,
+// b) or when the page has completely loaded including all subresources.
+//
+// The intent of this mechanism is to prevent user scripts from slowing down
+// fast pages (run after load), while still allowing them to run relatively
+// timelily for pages with lots of slow subresources.
+class UserScriptIdleScheduler {
+ public:
+  UserScriptIdleScheduler(RenderView* view, WebKit::WebFrame* frame);
+
+  bool has_run() { return has_run_; }
+
+  // Called when the DOM has been completely constructed.
+  void DidFinishDocumentLoad();
+
+  // Called when the document has completed loading.
+  void DidFinishLoad();
+
+  // Called when the client has gone away and we should no longer run scripts.
+  void Cancel();
+
+ private:
+  // Run user scripts, except if they've already run for this frame, or the
+  // frame has been destroyed.
+  void MaybeRun();
+
+  ScopedRunnableMethodFactory<UserScriptIdleScheduler> method_factory_;
+
+  // The RenderView we will call back to when it is time to run scripts.
+  RenderView* view_;
+
+  // The Frame we will run scripts in.
+  WebKit::WebFrame* frame_;
+
+  // Whether we have already run scripts.
+  bool has_run_;
+};
+
+#endif  // CHROME_RENDERER_USER_SCRIPT_IDLE_SCHEDULER_H_
diff --git a/chrome/test/data/extensions/good/Extensions/bjafgdebaacbbbecmhlhpofkepfkgcpa/1.0/page.js b/chrome/test/data/extensions/good/Extensions/bjafgdebaacbbbecmhlhpofkepfkgcpa/1.0/page.js
index 34d27fc654bde11b1cd333c5753e78f3ab7ae655..24f7a9ac3ec0d2634f653b3e75d44081cd9be4f1 100644
--- a/chrome/test/data/extensions/good/Extensions/bjafgdebaacbbbecmhlhpofkepfkgcpa/1.0/page.js
+++ b/chrome/test/data/extensions/good/Extensions/bjafgdebaacbbbecmhlhpofkepfkgcpa/1.0/page.js
@@ -3,28 +3,24 @@ if (typeof(contentWindow) != 'undefined') {
   win = contentWindow;
 }
 
-win.onload = function() {
-  // Do this in an onload handler because I'm not sure if chrome.extension
-  // is available before then.
-  chrome.extension.onConnect.addListener(function(port) {
-    console.log('connected');
-    port.onMessage.addListener(function(msg) {
-      console.log('got ' + msg);
-      if (msg.testPostMessage) {
-        port.postMessage({success: true});
-      } else if (msg.testPostMessageFromTab) {
-        testPostMessageFromTab(port);
-      } else if (msg.testDisconnect) {
-        port.disconnect();
-      } else if (msg.testDisconnectOnClose) {
-        win.location = "about:blank";
-      } else if (msg.testPortName) {
-        port.postMessage({portName:port.name});
-      }
-      // Ignore other messages since they are from us.
-    });
+chrome.extension.onConnect.addListener(function(port) {
+  console.log('connected');
+  port.onMessage.addListener(function(msg) {
+    console.log('got ' + msg);
+    if (msg.testPostMessage) {
+      port.postMessage({success: true});
+    } else if (msg.testPostMessageFromTab) {
+      testPostMessageFromTab(port);
+    } else if (msg.testDisconnect) {
+      port.disconnect();
+    } else if (msg.testDisconnectOnClose) {
+      win.location = "about:blank";
+    } else if (msg.testPortName) {
+      port.postMessage({portName:port.name});
+    }
+    // Ignore other messages since they are from us.
   });
-};
+});
 
 // Tests that postMessage to the extension and its response works.
 function testPostMessageFromTab(origPort) {