summaryrefslogtreecommitdiffstats
path: root/extensions
diff options
context:
space:
mode:
authorjamescook@chromium.org <jamescook@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-05-01 22:04:06 +0000
committerjamescook@chromium.org <jamescook@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-05-01 22:04:06 +0000
commitb6cd47221942b3b7352a87d03dcce2855bed0e79 (patch)
treec027b9e8985f4a36db1cbcbecc91f366a06b54e1 /extensions
parentbb1855136eab4e0ab80f204aab56b433d09f66be (diff)
downloadchromium_src-b6cd47221942b3b7352a87d03dcce2855bed0e79.zip
chromium_src-b6cd47221942b3b7352a87d03dcce2855bed0e79.tar.gz
chromium_src-b6cd47221942b3b7352a87d03dcce2855bed0e79.tar.bz2
Move renderer ExtensionHelper into //extensions
This breaks another //extensions -> //chrome circular dependency. * Split out Chrome-specific parts of ExtensionHelper to ChromeExtensionHelper * Move ExtensionHelper to //extensions * Move UserScriptScheduler to //extensions (a dependency of ExtensionHelper) * Tighten DEPS BUG=162530 TEST=compiles, existing browser_tests TBR=bbudge@chromium.org for mechanical header file move touching chrome/renderer/pepper Review URL: https://codereview.chromium.org/261733002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@267647 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'extensions')
-rw-r--r--extensions/DEPS1
-rw-r--r--extensions/extensions.gyp14
-rw-r--r--extensions/renderer/console.cc2
-rw-r--r--extensions/renderer/dispatcher.cc2
-rw-r--r--extensions/renderer/event_bindings.cc2
-rw-r--r--extensions/renderer/extension_helper.cc349
-rw-r--r--extensions/renderer/extension_helper.h113
-rw-r--r--extensions/renderer/lazy_background_page_native_handler.cc2
-rw-r--r--extensions/renderer/runtime_custom_bindings.cc2
-rw-r--r--extensions/renderer/user_script_scheduler.cc280
-rw-r--r--extensions/renderer/user_script_scheduler.h95
11 files changed, 851 insertions, 11 deletions
diff --git a/extensions/DEPS b/extensions/DEPS
index 4dabc14..bb58d4f 100644
--- a/extensions/DEPS
+++ b/extensions/DEPS
@@ -13,7 +13,6 @@ include_rules = [
#
# TODO(jamescook): Remove these. http://crbug.com/162530
"!chrome/browser/chrome_notification_types.h",
- "!chrome/renderer/extensions/extension_helper.h",
"!grit/common_resources.h",
'!grit/extensions_api_resources.h',
# This is needed for renderer JS sources which should eventually move to
diff --git a/extensions/extensions.gyp b/extensions/extensions.gyp
index faa7790..4411dae6 100644
--- a/extensions/extensions.gyp
+++ b/extensions/extensions.gyp
@@ -413,6 +413,11 @@
{
'target_name': 'extensions_renderer',
'type': 'static_library',
+ 'dependencies': [
+ 'extensions_resources.gyp:extensions_resources',
+ '../chrome/chrome_resources.gyp:chrome_resources',
+ '../third_party/WebKit/public/blink.gyp:blink',
+ ],
'include_dirs': [
'..',
],
@@ -448,6 +453,8 @@
'renderer/dom_activity_logger.h',
'renderer/event_bindings.cc',
'renderer/event_bindings.h',
+ 'renderer/extension_helper.cc',
+ 'renderer/extension_helper.h',
'renderer/extensions_renderer_client.cc',
'renderer/extensions_renderer_client.h',
'renderer/extension_groups.h',
@@ -498,6 +505,8 @@
'renderer/test_features_native_handler.h',
'renderer/user_gestures_native_handler.cc',
'renderer/user_gestures_native_handler.h',
+ 'renderer/user_script_scheduler.cc',
+ 'renderer/user_script_scheduler.h',
'renderer/user_script_slave.cc',
'renderer/user_script_slave.h',
'renderer/utils_native_handler.cc',
@@ -507,11 +516,6 @@
'renderer/v8_schema_registry.cc',
'renderer/v8_schema_registry.h',
],
- 'dependencies': [
- 'extensions_resources.gyp:extensions_resources',
- '../chrome/chrome_resources.gyp:chrome_resources',
- '../third_party/WebKit/public/blink.gyp:blink',
- ],
# Disable c4267 warnings until we fix size_t to int truncations.
'msvs_disabled_warnings': [ 4267, ],
'conditions': [
diff --git a/extensions/renderer/console.cc b/extensions/renderer/console.cc
index f7ae995..7429104 100644
--- a/extensions/renderer/console.cc
+++ b/extensions/renderer/console.cc
@@ -10,10 +10,10 @@
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
-#include "chrome/renderer/extensions/extension_helper.h"
#include "content/public/renderer/render_view.h"
#include "content/public/renderer/render_view_visitor.h"
#include "extensions/renderer/dispatcher.h"
+#include "extensions/renderer/extension_helper.h"
#include "third_party/WebKit/public/web/WebConsoleMessage.h"
#include "third_party/WebKit/public/web/WebFrame.h"
#include "third_party/WebKit/public/web/WebView.h"
diff --git a/extensions/renderer/dispatcher.cc b/extensions/renderer/dispatcher.cc
index 93fa434..75b2e43 100644
--- a/extensions/renderer/dispatcher.cc
+++ b/extensions/renderer/dispatcher.cc
@@ -13,7 +13,6 @@
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "base/values.h"
-#include "chrome/renderer/extensions/extension_helper.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/url_constants.h"
#include "content/public/renderer/render_thread.h"
@@ -50,6 +49,7 @@
#include "extensions/renderer/dom_activity_logger.h"
#include "extensions/renderer/event_bindings.h"
#include "extensions/renderer/extension_groups.h"
+#include "extensions/renderer/extension_helper.h"
#include "extensions/renderer/extensions_renderer_client.h"
#include "extensions/renderer/file_system_natives.h"
#include "extensions/renderer/i18n_custom_bindings.h"
diff --git a/extensions/renderer/event_bindings.cc b/extensions/renderer/event_bindings.cc
index 0ebd08e..331e6512 100644
--- a/extensions/renderer/event_bindings.cc
+++ b/extensions/renderer/event_bindings.cc
@@ -13,7 +13,6 @@
#include "base/bind.h"
#include "base/lazy_instance.h"
#include "base/memory/scoped_ptr.h"
-#include "chrome/renderer/extensions/extension_helper.h"
#include "content/public/renderer/render_thread.h"
#include "content/public/renderer/render_view.h"
#include "content/public/renderer/v8_value_converter.h"
@@ -23,6 +22,7 @@
#include "extensions/common/manifest_handlers/background_info.h"
#include "extensions/common/value_counter.h"
#include "extensions/renderer/dispatcher.h"
+#include "extensions/renderer/extension_helper.h"
#include "extensions/renderer/object_backed_native_handler.h"
#include "url/gurl.h"
#include "v8/include/v8.h"
diff --git a/extensions/renderer/extension_helper.cc b/extensions/renderer/extension_helper.cc
new file mode 100644
index 0000000..915097b
--- /dev/null
+++ b/extensions/renderer/extension_helper.cc
@@ -0,0 +1,349 @@
+// Copyright 2014 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 "extensions/renderer/extension_helper.h"
+
+#include "base/lazy_instance.h"
+#include "content/public/renderer/render_view.h"
+#include "content/public/renderer/render_view_visitor.h"
+#include "extensions/common/api/messaging/message.h"
+#include "extensions/common/constants.h"
+#include "extensions/common/extension_messages.h"
+#include "extensions/renderer/console.h"
+#include "extensions/renderer/dispatcher.h"
+#include "extensions/renderer/messaging_bindings.h"
+#include "extensions/renderer/user_script_scheduler.h"
+#include "extensions/renderer/user_script_slave.h"
+#include "third_party/WebKit/public/platform/WebURLRequest.h"
+#include "third_party/WebKit/public/web/WebConsoleMessage.h"
+#include "third_party/WebKit/public/web/WebDocument.h"
+#include "third_party/WebKit/public/web/WebLocalFrame.h"
+#include "third_party/WebKit/public/web/WebScopedUserGesture.h"
+#include "third_party/WebKit/public/web/WebView.h"
+
+using content::ConsoleMessageLevel;
+using blink::WebConsoleMessage;
+using blink::WebDataSource;
+using blink::WebFrame;
+using blink::WebLocalFrame;
+using blink::WebURLRequest;
+using blink::WebScopedUserGesture;
+using blink::WebView;
+
+namespace extensions {
+
+namespace {
+// Keeps a mapping from the frame pointer to a UserScriptScheduler object.
+// We store this mapping per process, because a frame can jump from one
+// document to another with adoptNode, and so having the object be a
+// RenderViewObserver means it might miss some notifications after it moves.
+typedef std::map<WebFrame*, UserScriptScheduler*> SchedulerMap;
+static base::LazyInstance<SchedulerMap> g_schedulers =
+ LAZY_INSTANCE_INITIALIZER;
+
+// A RenderViewVisitor class that iterates through the set of available
+// views, looking for a view of the given type, in the given browser window
+// and within the given extension.
+// Used to accumulate the list of views associated with an extension.
+class ViewAccumulator : public content::RenderViewVisitor {
+ public:
+ ViewAccumulator(const std::string& extension_id,
+ int browser_window_id,
+ ViewType view_type)
+ : extension_id_(extension_id),
+ browser_window_id_(browser_window_id),
+ view_type_(view_type) {
+ }
+
+ std::vector<content::RenderView*> views() { return views_; }
+
+ // Returns false to terminate the iteration.
+ virtual bool Visit(content::RenderView* render_view) OVERRIDE {
+ ExtensionHelper* helper = ExtensionHelper::Get(render_view);
+ if (!ViewTypeMatches(helper->view_type(), view_type_))
+ return true;
+
+ GURL url = render_view->GetWebView()->mainFrame()->document().url();
+ if (!url.SchemeIs(kExtensionScheme))
+ return true;
+ const std::string& extension_id = url.host();
+ if (extension_id != extension_id_)
+ return true;
+
+ if (browser_window_id_ != extension_misc::kUnknownWindowId &&
+ helper->browser_window_id() != browser_window_id_) {
+ return true;
+ }
+
+ views_.push_back(render_view);
+
+ if (view_type_ == VIEW_TYPE_EXTENSION_BACKGROUND_PAGE)
+ return false; // There can be only one...
+ return true;
+ }
+
+ private:
+ // Returns true if |type| "isa" |match|.
+ static bool ViewTypeMatches(ViewType type, ViewType match) {
+ if (type == match)
+ return true;
+
+ // INVALID means match all.
+ if (match == VIEW_TYPE_INVALID)
+ return true;
+
+ return false;
+ }
+
+ std::string extension_id_;
+ int browser_window_id_;
+ ViewType view_type_;
+ std::vector<content::RenderView*> views_;
+};
+
+} // namespace
+
+// static
+std::vector<content::RenderView*> ExtensionHelper::GetExtensionViews(
+ const std::string& extension_id,
+ int browser_window_id,
+ ViewType view_type) {
+ ViewAccumulator accumulator(extension_id, browser_window_id, view_type);
+ content::RenderView::ForEach(&accumulator);
+ return accumulator.views();
+}
+
+// static
+content::RenderView* ExtensionHelper::GetBackgroundPage(
+ const std::string& extension_id) {
+ ViewAccumulator accumulator(extension_id, extension_misc::kUnknownWindowId,
+ VIEW_TYPE_EXTENSION_BACKGROUND_PAGE);
+ content::RenderView::ForEach(&accumulator);
+ CHECK_LE(accumulator.views().size(), 1u);
+ if (accumulator.views().size() == 0)
+ return NULL;
+ return accumulator.views()[0];
+}
+
+ExtensionHelper::ExtensionHelper(content::RenderView* render_view,
+ Dispatcher* dispatcher)
+ : content::RenderViewObserver(render_view),
+ content::RenderViewObserverTracker<ExtensionHelper>(render_view),
+ dispatcher_(dispatcher),
+ view_type_(VIEW_TYPE_INVALID),
+ tab_id_(-1),
+ browser_window_id_(-1) {
+}
+
+ExtensionHelper::~ExtensionHelper() {
+}
+
+bool ExtensionHelper::OnMessageReceived(const IPC::Message& message) {
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(ExtensionHelper, message)
+ IPC_MESSAGE_HANDLER(ExtensionMsg_Response, OnExtensionResponse)
+ IPC_MESSAGE_HANDLER(ExtensionMsg_MessageInvoke, OnExtensionMessageInvoke)
+ IPC_MESSAGE_HANDLER(ExtensionMsg_DispatchOnConnect,
+ OnExtensionDispatchOnConnect)
+ IPC_MESSAGE_HANDLER(ExtensionMsg_DeliverMessage, OnExtensionDeliverMessage)
+ IPC_MESSAGE_HANDLER(ExtensionMsg_DispatchOnDisconnect,
+ OnExtensionDispatchOnDisconnect)
+ IPC_MESSAGE_HANDLER(ExtensionMsg_ExecuteCode, OnExecuteCode)
+ IPC_MESSAGE_HANDLER(ExtensionMsg_SetTabId, OnSetTabId)
+ IPC_MESSAGE_HANDLER(ExtensionMsg_UpdateBrowserWindowId,
+ OnUpdateBrowserWindowId)
+ IPC_MESSAGE_HANDLER(ExtensionMsg_NotifyRenderViewType,
+ OnNotifyRendererViewType)
+ IPC_MESSAGE_HANDLER(ExtensionMsg_AddMessageToConsole,
+ OnAddMessageToConsole)
+ IPC_MESSAGE_HANDLER(ExtensionMsg_AppWindowClosed,
+ OnAppWindowClosed);
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+ return handled;
+}
+
+void ExtensionHelper::DidFinishDocumentLoad(WebLocalFrame* frame) {
+ dispatcher_->user_script_slave()->InjectScripts(
+ frame, UserScript::DOCUMENT_END);
+
+ SchedulerMap::iterator i = g_schedulers.Get().find(frame);
+ if (i != g_schedulers.Get().end())
+ i->second->DidFinishDocumentLoad();
+}
+
+void ExtensionHelper::DidFinishLoad(blink::WebLocalFrame* frame) {
+ SchedulerMap::iterator i = g_schedulers.Get().find(frame);
+ if (i != g_schedulers.Get().end())
+ i->second->DidFinishLoad();
+}
+
+void ExtensionHelper::DidCreateDocumentElement(WebLocalFrame* frame) {
+ dispatcher_->user_script_slave()->InjectScripts(
+ frame, UserScript::DOCUMENT_START);
+ SchedulerMap::iterator i = g_schedulers.Get().find(frame);
+ if (i != g_schedulers.Get().end())
+ i->second->DidCreateDocumentElement();
+
+ dispatcher_->DidCreateDocumentElement(frame);
+}
+
+void ExtensionHelper::DidStartProvisionalLoad(blink::WebLocalFrame* frame) {
+ SchedulerMap::iterator i = g_schedulers.Get().find(frame);
+ if (i != g_schedulers.Get().end())
+ i->second->DidStartProvisionalLoad();
+}
+
+void ExtensionHelper::DraggableRegionsChanged(blink::WebFrame* frame) {
+ blink::WebVector<blink::WebDraggableRegion> webregions =
+ frame->document().draggableRegions();
+ std::vector<DraggableRegion> regions;
+ for (size_t i = 0; i < webregions.size(); ++i) {
+ DraggableRegion region;
+ region.bounds = webregions[i].bounds;
+ region.draggable = webregions[i].draggable;
+ regions.push_back(region);
+ }
+ Send(new ExtensionHostMsg_UpdateDraggableRegions(routing_id(), regions));
+}
+
+void ExtensionHelper::FrameDetached(WebFrame* frame) {
+ // This could be called before DidCreateDataSource, in which case the frame
+ // won't be in the map.
+ SchedulerMap::iterator i = g_schedulers.Get().find(frame);
+ if (i == g_schedulers.Get().end())
+ return;
+
+ delete i->second;
+ g_schedulers.Get().erase(i);
+}
+
+void ExtensionHelper::DidMatchCSS(
+ blink::WebLocalFrame* frame,
+ const blink::WebVector<blink::WebString>& newly_matching_selectors,
+ const blink::WebVector<blink::WebString>& stopped_matching_selectors) {
+ dispatcher_->DidMatchCSS(
+ frame, newly_matching_selectors, stopped_matching_selectors);
+}
+
+void ExtensionHelper::DidCreateDataSource(WebLocalFrame* frame,
+ WebDataSource* ds) {
+ // Check first if we created a scheduler for the frame, since this function
+ // gets called for navigations within the document.
+ if (g_schedulers.Get().count(frame))
+ return;
+
+ g_schedulers.Get()[frame] = new UserScriptScheduler(frame, dispatcher_);
+}
+
+void ExtensionHelper::OnExtensionResponse(int request_id,
+ bool success,
+ const base::ListValue& response,
+ const std::string& error) {
+ dispatcher_->OnExtensionResponse(request_id,
+ success,
+ response,
+ error);
+}
+
+void ExtensionHelper::OnExtensionMessageInvoke(const std::string& extension_id,
+ const std::string& module_name,
+ const std::string& function_name,
+ const base::ListValue& args,
+ bool user_gesture) {
+ dispatcher_->InvokeModuleSystemMethod(
+ render_view(), extension_id, module_name, function_name, args,
+ user_gesture);
+}
+
+void ExtensionHelper::OnExtensionDispatchOnConnect(
+ int target_port_id,
+ const std::string& channel_name,
+ const base::DictionaryValue& source_tab,
+ const ExtensionMsg_ExternalConnectionInfo& info,
+ const std::string& tls_channel_id) {
+ MessagingBindings::DispatchOnConnect(
+ dispatcher_->script_context_set().GetAll(),
+ target_port_id,
+ channel_name,
+ source_tab,
+ info.source_id,
+ info.target_id,
+ info.source_url,
+ tls_channel_id,
+ render_view());
+}
+
+void ExtensionHelper::OnExtensionDeliverMessage(int target_id,
+ const Message& message) {
+ MessagingBindings::DeliverMessage(dispatcher_->script_context_set().GetAll(),
+ target_id,
+ message,
+ render_view());
+}
+
+void ExtensionHelper::OnExtensionDispatchOnDisconnect(
+ int port_id,
+ const std::string& error_message) {
+ MessagingBindings::DispatchOnDisconnect(
+ dispatcher_->script_context_set().GetAll(),
+ port_id,
+ error_message,
+ render_view());
+}
+
+void ExtensionHelper::OnExecuteCode(
+ const ExtensionMsg_ExecuteCode_Params& params) {
+ WebView* webview = render_view()->GetWebView();
+ WebFrame* main_frame = webview->mainFrame();
+ if (!main_frame) {
+ base::ListValue val;
+ Send(new ExtensionHostMsg_ExecuteCodeFinished(routing_id(),
+ params.request_id,
+ "No main frame",
+ -1,
+ GURL(std::string()),
+ val));
+ return;
+ }
+
+ // chrome.tabs.executeScript() only supports execution in either the top frame
+ // or all frames. We handle both cases in the top frame.
+ SchedulerMap::iterator i = g_schedulers.Get().find(main_frame);
+ if (i != g_schedulers.Get().end())
+ i->second->ExecuteCode(params);
+}
+
+void ExtensionHelper::OnNotifyRendererViewType(ViewType type) {
+ view_type_ = type;
+}
+
+void ExtensionHelper::OnSetTabId(int init_tab_id) {
+ CHECK_EQ(tab_id_, -1);
+ CHECK_GE(init_tab_id, 0);
+ tab_id_ = init_tab_id;
+}
+
+void ExtensionHelper::OnUpdateBrowserWindowId(int window_id) {
+ browser_window_id_ = window_id;
+}
+
+void ExtensionHelper::OnAddMessageToConsole(ConsoleMessageLevel level,
+ const std::string& message) {
+ console::AddMessage(render_view(), level, message);
+}
+
+void ExtensionHelper::OnAppWindowClosed() {
+ v8::HandleScope scope(v8::Isolate::GetCurrent());
+ v8::Handle<v8::Context> v8_context =
+ render_view()->GetWebView()->mainFrame()->mainWorldScriptContext();
+ ScriptContext* script_context =
+ dispatcher_->script_context_set().GetByV8Context(v8_context);
+ if (!script_context)
+ return;
+ script_context->module_system()->CallModuleMethod("app.window",
+ "onAppWindowClosed");
+}
+
+} // namespace extensions
diff --git a/extensions/renderer/extension_helper.h b/extensions/renderer/extension_helper.h
new file mode 100644
index 0000000..486db54
--- /dev/null
+++ b/extensions/renderer/extension_helper.h
@@ -0,0 +1,113 @@
+// Copyright 2014 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 EXTENSIONS_RENDERER_EXTENSION_HELPER_H_
+#define EXTENSIONS_RENDERER_EXTENSION_HELPER_H_
+
+#include <vector>
+
+#include "content/public/common/console_message_level.h"
+#include "content/public/renderer/render_view_observer.h"
+#include "content/public/renderer/render_view_observer_tracker.h"
+#include "extensions/common/view_type.h"
+
+class GURL;
+class SkBitmap;
+struct ExtensionMsg_ExecuteCode_Params;
+struct ExtensionMsg_ExternalConnectionInfo;
+
+namespace base {
+class DictionaryValue;
+class ListValue;
+}
+
+namespace extensions {
+class Dispatcher;
+struct Message;
+
+// RenderView-level plumbing for extension features.
+class ExtensionHelper
+ : public content::RenderViewObserver,
+ public content::RenderViewObserverTracker<ExtensionHelper> {
+ public:
+ // Returns a list of extension RenderViews that match the given filter
+ // criteria. If |browser_window_id| is not extension_misc::kUnknownWindowId,
+ // the list is restricted to views in that browser window.
+ static std::vector<content::RenderView*> GetExtensionViews(
+ const std::string& extension_id,
+ int browser_window_id,
+ ViewType view_type);
+
+ // Returns the given extension's background page, or NULL if none.
+ static content::RenderView* GetBackgroundPage(
+ const std::string& extension_id);
+
+ ExtensionHelper(content::RenderView* render_view, Dispatcher* dispatcher);
+ virtual ~ExtensionHelper();
+
+ int tab_id() const { return tab_id_; }
+ int browser_window_id() const { return browser_window_id_; }
+ ViewType view_type() const { return view_type_; }
+ Dispatcher* dispatcher() const { return dispatcher_; }
+
+ private:
+ // RenderViewObserver implementation.
+ virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
+ virtual void DidFinishDocumentLoad(blink::WebLocalFrame* frame) OVERRIDE;
+ virtual void DidFinishLoad(blink::WebLocalFrame* frame) OVERRIDE;
+ virtual void DidCreateDocumentElement(blink::WebLocalFrame* frame) OVERRIDE;
+ virtual void DidStartProvisionalLoad(blink::WebLocalFrame* frame) OVERRIDE;
+ virtual void FrameDetached(blink::WebFrame* frame) OVERRIDE;
+ virtual void DidMatchCSS(
+ blink::WebLocalFrame* frame,
+ const blink::WebVector<blink::WebString>& newly_matching_selectors,
+ const blink::WebVector<blink::WebString>& stopped_matching_selectors)
+ OVERRIDE;
+ virtual void DidCreateDataSource(blink::WebLocalFrame* frame,
+ blink::WebDataSource* ds) OVERRIDE;
+ virtual void DraggableRegionsChanged(blink::WebFrame* frame) OVERRIDE;
+
+ void OnExtensionResponse(int request_id, bool success,
+ const base::ListValue& response,
+ const std::string& error);
+ void OnExtensionMessageInvoke(const std::string& extension_id,
+ const std::string& module_name,
+ const std::string& function_name,
+ const base::ListValue& args,
+ bool user_gesture);
+ void OnExtensionDispatchOnConnect(
+ int target_port_id,
+ const std::string& channel_name,
+ const base::DictionaryValue& source_tab,
+ const ExtensionMsg_ExternalConnectionInfo& info,
+ const std::string& tls_channel_id);
+ void OnExtensionDeliverMessage(int target_port_id,
+ const Message& message);
+ void OnExtensionDispatchOnDisconnect(int port_id,
+ const std::string& error_message);
+ void OnExecuteCode(const ExtensionMsg_ExecuteCode_Params& params);
+ void OnNotifyRendererViewType(ViewType view_type);
+ void OnSetTabId(int tab_id);
+ void OnUpdateBrowserWindowId(int window_id);
+ void OnAddMessageToConsole(content::ConsoleMessageLevel level,
+ const std::string& message);
+ void OnAppWindowClosed();
+
+ Dispatcher* dispatcher_;
+
+ // Type of view attached with RenderView.
+ ViewType view_type_;
+
+ // Id of the tab which the RenderView is attached to.
+ int tab_id_;
+
+ // Id number of browser window which RenderView is attached to.
+ int browser_window_id_;
+
+ DISALLOW_COPY_AND_ASSIGN(ExtensionHelper);
+};
+
+} // namespace extensions
+
+#endif // EXTENSIONS_RENDERER_EXTENSION_HELPER_H_
diff --git a/extensions/renderer/lazy_background_page_native_handler.cc b/extensions/renderer/lazy_background_page_native_handler.cc
index b7c72cd..c8a31fe 100644
--- a/extensions/renderer/lazy_background_page_native_handler.cc
+++ b/extensions/renderer/lazy_background_page_native_handler.cc
@@ -5,10 +5,10 @@
#include "extensions/renderer/lazy_background_page_native_handler.h"
#include "base/bind.h"
-#include "chrome/renderer/extensions/extension_helper.h"
#include "content/public/renderer/render_view.h"
#include "extensions/common/extension_messages.h"
#include "extensions/common/manifest_handlers/background_info.h"
+#include "extensions/renderer/extension_helper.h"
#include "extensions/renderer/script_context.h"
namespace extensions {
diff --git a/extensions/renderer/runtime_custom_bindings.cc b/extensions/renderer/runtime_custom_bindings.cc
index 7ed2ad2..3815abc 100644
--- a/extensions/renderer/runtime_custom_bindings.cc
+++ b/extensions/renderer/runtime_custom_bindings.cc
@@ -7,7 +7,6 @@
#include "base/bind.h"
#include "base/memory/scoped_ptr.h"
#include "base/values.h"
-#include "chrome/renderer/extensions/extension_helper.h"
#include "content/public/renderer/render_view.h"
#include "content/public/renderer/v8_value_converter.h"
#include "extensions/common/extension.h"
@@ -16,6 +15,7 @@
#include "extensions/common/features/feature_provider.h"
#include "extensions/common/manifest.h"
#include "extensions/renderer/api_activity_logger.h"
+#include "extensions/renderer/extension_helper.h"
#include "extensions/renderer/script_context.h"
#include "third_party/WebKit/public/web/WebDocument.h"
#include "third_party/WebKit/public/web/WebFrame.h"
diff --git a/extensions/renderer/user_script_scheduler.cc b/extensions/renderer/user_script_scheduler.cc
new file mode 100644
index 0000000..9c82fb7a
--- /dev/null
+++ b/extensions/renderer/user_script_scheduler.cc
@@ -0,0 +1,280 @@
+// Copyright 2014 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 "extensions/renderer/user_script_scheduler.h"
+
+#include "base/bind.h"
+#include "base/logging.h"
+#include "base/message_loop/message_loop.h"
+#include "content/public/renderer/render_view.h"
+#include "content/public/renderer/v8_value_converter.h"
+#include "extensions/common/error_utils.h"
+#include "extensions/common/extension_messages.h"
+#include "extensions/common/manifest_constants.h"
+#include "extensions/common/permissions/permissions_data.h"
+#include "extensions/renderer/dispatcher.h"
+#include "extensions/renderer/dom_activity_logger.h"
+#include "extensions/renderer/extension_groups.h"
+#include "extensions/renderer/extension_helper.h"
+#include "extensions/renderer/script_context.h"
+#include "extensions/renderer/user_script_slave.h"
+#include "third_party/WebKit/public/platform/WebString.h"
+#include "third_party/WebKit/public/platform/WebVector.h"
+#include "third_party/WebKit/public/web/WebDocument.h"
+#include "third_party/WebKit/public/web/WebFrame.h"
+#include "third_party/WebKit/public/web/WebScopedUserGesture.h"
+#include "third_party/WebKit/public/web/WebView.h"
+#include "v8/include/v8.h"
+
+namespace {
+// The length of time to wait after the DOM is complete to try and run user
+// scripts.
+const int kUserScriptIdleTimeoutMs = 200;
+}
+
+using blink::WebDocument;
+using blink::WebFrame;
+using blink::WebString;
+using blink::WebVector;
+using blink::WebView;
+
+namespace extensions {
+
+UserScriptScheduler::UserScriptScheduler(WebFrame* frame,
+ Dispatcher* dispatcher)
+ : weak_factory_(this),
+ frame_(frame),
+ current_location_(UserScript::UNDEFINED),
+ has_run_idle_(false),
+ dispatcher_(dispatcher) {
+ for (int i = UserScript::UNDEFINED; i < UserScript::RUN_LOCATION_LAST; ++i) {
+ pending_execution_map_[static_cast<UserScript::RunLocation>(i)] =
+ std::queue<linked_ptr<ExtensionMsg_ExecuteCode_Params> >();
+ }
+}
+
+UserScriptScheduler::~UserScriptScheduler() {
+}
+
+void UserScriptScheduler::ExecuteCode(
+ const ExtensionMsg_ExecuteCode_Params& params) {
+ UserScript::RunLocation run_at =
+ static_cast<UserScript::RunLocation>(params.run_at);
+ if (current_location_ < run_at) {
+ pending_execution_map_[run_at].push(
+ linked_ptr<ExtensionMsg_ExecuteCode_Params>(
+ new ExtensionMsg_ExecuteCode_Params(params)));
+ return;
+ }
+
+ ExecuteCodeImpl(params);
+}
+
+void UserScriptScheduler::DidCreateDocumentElement() {
+ current_location_ = UserScript::DOCUMENT_START;
+ MaybeRun();
+}
+
+void UserScriptScheduler::DidFinishDocumentLoad() {
+ current_location_ = UserScript::DOCUMENT_END;
+ MaybeRun();
+ // Schedule a run for DOCUMENT_IDLE
+ base::MessageLoop::current()->PostDelayedTask(
+ FROM_HERE,
+ base::Bind(&UserScriptScheduler::IdleTimeout, weak_factory_.GetWeakPtr()),
+ base::TimeDelta::FromMilliseconds(kUserScriptIdleTimeoutMs));
+}
+
+void UserScriptScheduler::DidFinishLoad() {
+ current_location_ = UserScript::DOCUMENT_IDLE;
+ // Ensure that running scripts does not keep any progress UI running.
+ base::MessageLoop::current()->PostTask(
+ FROM_HERE,
+ base::Bind(&UserScriptScheduler::MaybeRun, weak_factory_.GetWeakPtr()));
+}
+
+void UserScriptScheduler::DidStartProvisionalLoad() {
+ // The frame is navigating, so reset the state since we'll want to inject
+ // scripts once the load finishes.
+ current_location_ = UserScript::UNDEFINED;
+ has_run_idle_ = false;
+ weak_factory_.InvalidateWeakPtrs();
+ std::map<UserScript::RunLocation, ExecutionQueue>::iterator itr =
+ pending_execution_map_.begin();
+ for (itr = pending_execution_map_.begin();
+ itr != pending_execution_map_.end(); ++itr) {
+ while (!itr->second.empty())
+ itr->second.pop();
+ }
+}
+
+void UserScriptScheduler::IdleTimeout() {
+ current_location_ = UserScript::DOCUMENT_IDLE;
+ MaybeRun();
+}
+
+void UserScriptScheduler::MaybeRun() {
+ if (current_location_ == UserScript::UNDEFINED)
+ return;
+
+ if (!has_run_idle_ && current_location_ == UserScript::DOCUMENT_IDLE) {
+ has_run_idle_ = true;
+ dispatcher_->user_script_slave()->InjectScripts(
+ frame_, UserScript::DOCUMENT_IDLE);
+ }
+
+ // Run all tasks from the current time and earlier.
+ for (int i = UserScript::DOCUMENT_START;
+ i <= current_location_; ++i) {
+ UserScript::RunLocation run_time = static_cast<UserScript::RunLocation>(i);
+ while (!pending_execution_map_[run_time].empty()) {
+ linked_ptr<ExtensionMsg_ExecuteCode_Params>& params =
+ pending_execution_map_[run_time].front();
+ ExecuteCodeImpl(*params);
+ pending_execution_map_[run_time].pop();
+ }
+ }
+}
+
+void UserScriptScheduler::ExecuteCodeImpl(
+ const ExtensionMsg_ExecuteCode_Params& params) {
+ const Extension* extension = dispatcher_->extensions()->GetByID(
+ params.extension_id);
+ content::RenderView* render_view =
+ content::RenderView::FromWebView(frame_->view());
+ ExtensionHelper* extension_helper = ExtensionHelper::Get(render_view);
+ base::ListValue execution_results;
+
+ // Since extension info is sent separately from user script info, they can
+ // be out of sync. We just ignore this situation.
+ if (!extension) {
+ render_view->Send(
+ new ExtensionHostMsg_ExecuteCodeFinished(render_view->GetRoutingID(),
+ params.request_id,
+ std::string(), // no error
+ -1,
+ GURL(std::string()),
+ execution_results));
+ return;
+ }
+
+ std::vector<WebFrame*> frame_vector;
+ frame_vector.push_back(frame_);
+ if (params.all_frames)
+ GetAllChildFrames(frame_, &frame_vector);
+
+ std::string error;
+
+ scoped_ptr<blink::WebScopedUserGesture> gesture;
+ if (params.user_gesture)
+ gesture.reset(new blink::WebScopedUserGesture);
+
+ GURL top_url = frame_->document().url();
+
+ for (std::vector<WebFrame*>::iterator frame_it = frame_vector.begin();
+ frame_it != frame_vector.end(); ++frame_it) {
+ WebFrame* child_frame = *frame_it;
+ CHECK(child_frame) << top_url;
+
+ // We recheck access here in the renderer for extra safety against races
+ // with navigation.
+ //
+ // But different frames can have different URLs, and the extension might
+ // only have access to a subset of them. For the top frame, we can
+ // immediately send an error and stop because the browser process
+ // considers that an error too.
+ //
+ // For child frames, we just skip ones the extension doesn't have access
+ // to and carry on.
+
+ bool can_execute_script =
+ PermissionsData::CanExecuteScriptOnPage(extension,
+ child_frame->document().url(),
+ top_url,
+ extension_helper->tab_id(),
+ NULL,
+ -1,
+ NULL);
+ if ((!params.is_web_view && !can_execute_script) ||
+ (params.is_web_view &&
+ child_frame->document().url() != params.webview_src)) {
+ if (child_frame->parent()) {
+ continue;
+ } else {
+ error = ErrorUtils::FormatErrorMessage(
+ manifest_errors::kCannotAccessPage,
+ child_frame->document().url().spec());
+ break;
+ }
+ }
+
+ if (params.is_javascript) {
+ WebScriptSource source(WebString::fromUTF8(params.code), params.file_url);
+ v8::HandleScope scope(v8::Isolate::GetCurrent());
+
+ scoped_ptr<content::V8ValueConverter> v8_converter(
+ content::V8ValueConverter::create());
+ v8::Local<v8::Value> script_value;
+
+ if (params.in_main_world) {
+ DOMActivityLogger::AttachToWorld(DOMActivityLogger::kMainWorldId,
+ extension->id());
+ script_value = child_frame->executeScriptAndReturnValue(source);
+ } else {
+ blink::WebVector<v8::Local<v8::Value> > results;
+ std::vector<WebScriptSource> sources;
+ sources.push_back(source);
+ int isolated_world_id =
+ dispatcher_->user_script_slave()->GetIsolatedWorldIdForExtension(
+ extension, child_frame);
+ DOMActivityLogger::AttachToWorld(isolated_world_id, extension->id());
+ child_frame->executeScriptInIsolatedWorld(
+ isolated_world_id, &sources.front(),
+ sources.size(), EXTENSION_GROUP_CONTENT_SCRIPTS, &results);
+ // We only expect one value back since we only pushed one source
+ if (results.size() == 1 && !results[0].IsEmpty())
+ script_value = results[0];
+ }
+
+ if (params.wants_result && !script_value.IsEmpty()) {
+ // It's safe to always use the main world context when converting here.
+ // V8ValueConverterImpl shouldn't actually care about the context scope,
+ // and it switches to v8::Object's creation context when encountered.
+ v8::Local<v8::Context> context = child_frame->mainWorldScriptContext();
+ base::Value* result = v8_converter->FromV8Value(script_value, context);
+ // Always append an execution result (i.e. no result == null result) so
+ // that |execution_results| lines up with the frames.
+ execution_results.Append(
+ result ? result : base::Value::CreateNullValue());
+ }
+ } else {
+ child_frame->document().insertStyleSheet(
+ WebString::fromUTF8(params.code));
+ }
+ }
+
+ render_view->Send(new ExtensionHostMsg_ExecuteCodeFinished(
+ render_view->GetRoutingID(),
+ params.request_id,
+ error,
+ render_view->GetPageId(),
+ ScriptContext::GetDataSourceURLForFrame(frame_),
+ execution_results));
+}
+
+bool UserScriptScheduler::GetAllChildFrames(
+ WebFrame* parent_frame,
+ std::vector<WebFrame*>* frames_vector) const {
+ if (!parent_frame)
+ return false;
+
+ for (WebFrame* child_frame = parent_frame->firstChild(); child_frame;
+ child_frame = child_frame->nextSibling()) {
+ frames_vector->push_back(child_frame);
+ GetAllChildFrames(child_frame, frames_vector);
+ }
+ return true;
+}
+
+} // namespace extensions
diff --git a/extensions/renderer/user_script_scheduler.h b/extensions/renderer/user_script_scheduler.h
new file mode 100644
index 0000000..4e8a45b
--- /dev/null
+++ b/extensions/renderer/user_script_scheduler.h
@@ -0,0 +1,95 @@
+// Copyright 2014 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 EXTENSIONS_RENDERER_USER_SCRIPT_SCHEDULER_H_
+#define EXTENSIONS_RENDERER_USER_SCRIPT_SCHEDULER_H_
+
+#include <map>
+#include <queue>
+
+#include "base/memory/linked_ptr.h"
+#include "base/memory/weak_ptr.h"
+#include "extensions/common/user_script.h"
+
+class RenderView;
+struct ExtensionMsg_ExecuteCode_Params;
+
+namespace blink {
+class WebFrame;
+}
+
+namespace extensions {
+class Dispatcher;
+
+// Implements support for injecting scripts at different times in the document
+// loading process. The different possible time are described in
+// UserScript::RunLocation.
+//
+// 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
+// timely for pages with lots of slow subresources.
+//
+// NOTE: this class does not inherit from RenderViewObserver on purpose. The
+// reason is that this object is per frame, and a frame can move across
+// RenderViews thanks to adoptNode. So we have each RenderView's
+// ExtensionHelper proxy these calls to the renderer process' Dispatcher,
+// which contains the mapping from WebFrame to us.
+class UserScriptScheduler {
+ public:
+ UserScriptScheduler(blink::WebFrame* frame, Dispatcher* dispatcher);
+ ~UserScriptScheduler();
+
+ void ExecuteCode(const ExtensionMsg_ExecuteCode_Params& params);
+ void DidCreateDocumentElement();
+ void DidFinishDocumentLoad();
+ void DidFinishLoad();
+ void DidStartProvisionalLoad();
+
+ private:
+ typedef
+ std::queue<linked_ptr<ExtensionMsg_ExecuteCode_Params> >
+ ExecutionQueue;
+
+ // Run user scripts, except if they've already run for this frame, or the
+ // frame has been destroyed.
+ void MaybeRun();
+
+ // Backend for the IPC Message ExecuteCode in addition to being used
+ // internally.
+ void ExecuteCodeImpl(const ExtensionMsg_ExecuteCode_Params& params);
+
+ // Get all child frames of parent_frame, returned by frames_vector.
+ bool GetAllChildFrames(blink::WebFrame* parent_frame,
+ std::vector<blink::WebFrame*>* frames_vector) const;
+
+ // Call to signify thet the idle timeout has expired.
+ void IdleTimeout();
+
+ base::WeakPtrFactory<UserScriptScheduler> weak_factory_;
+
+ // The Frame we will run scripts in.
+ blink::WebFrame* frame_;
+
+ // The current location in the document loading process.
+ // Will be UserScript::UNDEFINED if it is before any scripts should be run.
+ UserScript::RunLocation current_location_;
+
+ // Whether we have already run the idle scripts.
+ bool has_run_idle_;
+
+ // This is only used if we're for the main frame.
+ std::map<UserScript::RunLocation, ExecutionQueue> pending_execution_map_;
+
+ Dispatcher* dispatcher_;
+};
+
+} // namespace extensions
+
+#endif // EXTENSIONS_RENDERER_USER_SCRIPT_SCHEDULER_H_