summaryrefslogtreecommitdiffstats
path: root/chrome/renderer/extensions
diff options
context:
space:
mode:
authorerikkay@chromium.org <erikkay@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-08-12 20:12:42 +0000
committererikkay@chromium.org <erikkay@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-08-12 20:12:42 +0000
commit6d7a6046d581348565fc0634d81efce653a1f550 (patch)
treed7f2b7ca49c1805d11dea9751adea02a0562a939 /chrome/renderer/extensions
parent0ba9330a17a3fd294a28972f5a81b64f550e6a20 (diff)
downloadchromium_src-6d7a6046d581348565fc0634d81efce653a1f550.zip
chromium_src-6d7a6046d581348565fc0634d81efce653a1f550.tar.gz
chromium_src-6d7a6046d581348565fc0634d81efce653a1f550.tar.bz2
remove toolstrips
BUG=51703 BUG=30178 BUG=25106 TEST=none Review URL: http://codereview.chromium.org/3129003 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@55921 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/renderer/extensions')
-rw-r--r--chrome/renderer/extensions/extension_process_bindings.cc1432
-rw-r--r--chrome/renderer/extensions/extension_process_bindings.h5
2 files changed, 700 insertions, 737 deletions
diff --git a/chrome/renderer/extensions/extension_process_bindings.cc b/chrome/renderer/extensions/extension_process_bindings.cc
index 8057e67..1a97872 100644
--- a/chrome/renderer/extensions/extension_process_bindings.cc
+++ b/chrome/renderer/extensions/extension_process_bindings.cc
@@ -1,732 +1,700 @@
-// Copyright (c) 2010 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/extensions/extension_process_bindings.h"
-
-#include <map>
-#include <set>
-#include <string>
-#include <vector>
-
-#include "base/command_line.h"
-#include "base/json/json_reader.h"
-#include "base/scoped_ptr.h"
-#include "base/singleton.h"
-#include "base/string_util.h"
-#include "chrome/common/chrome_switches.h"
-#include "chrome/common/extensions/extension.h"
-#include "chrome/common/extensions/extension_constants.h"
-#include "chrome/common/extensions/url_pattern.h"
-#include "chrome/common/render_messages.h"
-#include "chrome/common/url_constants.h"
-#include "chrome/renderer/extensions/bindings_utils.h"
-#include "chrome/renderer/extensions/event_bindings.h"
-#include "chrome/renderer/extensions/js_only_v8_extensions.h"
-#include "chrome/renderer/extensions/renderer_extension_bindings.h"
-#include "chrome/renderer/user_script_slave.h"
-#include "chrome/renderer/render_thread.h"
-#include "chrome/renderer/render_view.h"
-#include "chrome/renderer/render_view_visitor.h"
-#include "grit/common_resources.h"
-#include "grit/renderer_resources.h"
-#include "third_party/skia/include/core/SkBitmap.h"
-#include "third_party/skia/include/core/SkColor.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebFrame.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebURL.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebKit.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebSecurityPolicy.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebView.h"
-
-using bindings_utils::GetStringResource;
-using bindings_utils::ContextInfo;
-using bindings_utils::ContextList;
-using bindings_utils::GetContexts;
-using bindings_utils::GetPendingRequestMap;
-using bindings_utils::PendingRequest;
-using bindings_utils::PendingRequestMap;
-using bindings_utils::ExtensionBase;
-using WebKit::WebFrame;
-using WebKit::WebSecurityPolicy;
-using WebKit::WebView;
-
-namespace {
-
-// A map of extension ID to vector of page action ids.
-typedef std::map< std::string, std::vector<std::string> > PageActionIdMap;
-
-// A map of permission name to whether its enabled for this extension.
-typedef std::map<std::string, bool> PermissionsMap;
-
-// A map of extension ID to permissions map.
-typedef std::map<std::string, PermissionsMap> ExtensionPermissionsMap;
-
-// A map of extension ID to whether this extension was enabled in incognito.
-typedef std::map<std::string, bool> IncognitoEnabledMap;
-
-const char kExtensionName[] = "chrome/ExtensionProcessBindings";
-const char* kExtensionDeps[] = {
- BaseJsV8Extension::kName,
- EventBindings::kName,
- JsonSchemaJsV8Extension::kName,
- RendererExtensionBindings::kName,
- ExtensionApiTestV8Extension::kName,
-};
-
-// A list of the API packages which have no associated permission.
-// TODO(erikkay) It might be nice if for consistency we could merge these with
-// the permissions list, or at least have them in one place.
-const char* kNonPermissionExtensionPackages[] = {
- "extension",
- // TODO(erikkay): We're inconsistent about the the package name in the events
- // for pageAction and browserAction.
- "pageAction",
- "pageActions",
- "browserAction",
- "browserActions",
- "i18n",
- "devtools",
- "test"
-};
-
-struct SingletonData {
- std::set<std::string> function_names_;
- PageActionIdMap page_action_ids_;
- ExtensionPermissionsMap permissions_;
- IncognitoEnabledMap incognito_enabled_map_;
-};
-
-static std::set<std::string>* GetFunctionNameSet() {
- return &Singleton<SingletonData>()->function_names_;
-}
-
-static PageActionIdMap* GetPageActionMap() {
- return &Singleton<SingletonData>()->page_action_ids_;
-}
-
-static PermissionsMap* GetPermissionsMap(const std::string& extension_id) {
- return &Singleton<SingletonData>()->permissions_[extension_id];
-}
-
-static IncognitoEnabledMap* GetIncognitoEnabledMap() {
- return &Singleton<SingletonData>()->incognito_enabled_map_;
-}
-
-static void GetActiveExtensionIDs(std::set<std::string>* extension_ids) {
- ExtensionPermissionsMap& permissions =
- Singleton<SingletonData>()->permissions_;
-
- for (ExtensionPermissionsMap::iterator iter = permissions.begin();
- iter != permissions.end(); ++iter) {
- extension_ids->insert(iter->first);
- }
-}
-
-// 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 ExtensionViewAccumulator : public RenderViewVisitor {
- public:
- ExtensionViewAccumulator(const std::string& extension_id,
- int browser_window_id,
- ViewType::Type view_type)
- : extension_id_(extension_id),
- browser_window_id_(browser_window_id),
- view_type_(view_type),
- views_(v8::Array::New()),
- index_(0) {
- }
-
- v8::Local<v8::Array> views() { return views_; }
-
- virtual bool Visit(RenderView* render_view) {
- if (!ViewTypeMatches(render_view->view_type(), view_type_))
- return true;
-
- GURL url = render_view->webview()->mainFrame()->url();
- if (!url.SchemeIs(chrome::kExtensionScheme))
- return true;
- const std::string& extension_id = url.host();
- if (extension_id != extension_id_)
- return true;
-
- // If we are searching for a pop-up, it may be the case that the pop-up
- // is not attached to a browser window instance. (It is hosted in a
- // ExternalTabContainer.) If so, then bypass validation of
- // same-browser-window origin.
- // TODO(twiz): The browser window id of the views visited should always
- // match that of the arguments to the accumulator.
- // See bug: http://crbug.com/29646
- if (!(view_type_ == ViewType::EXTENSION_POPUP &&
- render_view->browser_window_id() ==
- extension_misc::kUnknownWindowId)) {
- if (browser_window_id_ != extension_misc::kUnknownWindowId &&
- render_view->browser_window_id() != browser_window_id_) {
- return true;
- }
- }
-
- v8::Local<v8::Context> context =
- render_view->webview()->mainFrame()->mainWorldScriptContext();
- if (!context.IsEmpty()) {
- v8::Local<v8::Value> window = context->Global();
- DCHECK(!window.IsEmpty());
-
- if (!OnMatchedView(window))
- return false;
- }
- return true;
- }
-
- private:
- // Called on each view found matching the search criteria. Returns false
- // to terminate the iteration.
- bool OnMatchedView(const v8::Local<v8::Value>& view_window) {
- views_->Set(v8::Integer::New(index_), view_window);
- index_++;
-
- if (view_type_ == ViewType::EXTENSION_BACKGROUND_PAGE)
- return false; // There can be only one...
-
- return true;
- }
-
- // Returns true is |type| "isa" |match|.
- static bool ViewTypeMatches(ViewType::Type type, ViewType::Type match) {
- if (type == match)
- return true;
-
- // INVALID means match all.
- if (match == ViewType::INVALID)
- return true;
-
- // TODO(erikkay) for now, special case mole as a type of toolstrip.
- // Perhaps this isn't the right long-term thing to do.
- if (match == ViewType::EXTENSION_TOOLSTRIP &&
- type == ViewType::EXTENSION_MOLE) {
- return true;
- }
-
- return false;
- }
-
- std::string extension_id_;
- int browser_window_id_;
- ViewType::Type view_type_;
- v8::Local<v8::Array> views_;
- int index_;
-};
-
-class ExtensionImpl : public ExtensionBase {
- public:
- ExtensionImpl() : ExtensionBase(
- kExtensionName, GetStringResource<IDR_EXTENSION_PROCESS_BINDINGS_JS>(),
- arraysize(kExtensionDeps), kExtensionDeps) {}
-
- static void SetFunctionNames(const std::vector<std::string>& names) {
- std::set<std::string>* name_set = GetFunctionNameSet();
- for (size_t i = 0; i < names.size(); ++i) {
- name_set->insert(names[i]);
- }
- }
-
- // Note: do not call this function before or during the chromeHidden.onLoad
- // event dispatch. The URL might not have been committed yet and might not
- // be an extension URL.
- static std::string ExtensionIdForCurrentContext() {
- RenderView* renderview = bindings_utils::GetRenderViewForCurrentContext();
- if (!renderview)
- return std::string(); // this can happen as a tab is closing.
-
- GURL url = renderview->webview()->mainFrame()->url();
- if (!url.SchemeIs(chrome::kExtensionScheme))
- return std::string();
-
- return url.host();
- }
-
- virtual v8::Handle<v8::FunctionTemplate> GetNativeFunction(
- v8::Handle<v8::String> name) {
- if (name->Equals(v8::String::New("GetExtensionAPIDefinition"))) {
- return v8::FunctionTemplate::New(GetExtensionAPIDefinition);
- } else if (name->Equals(v8::String::New("GetExtensionViews"))) {
- return v8::FunctionTemplate::New(GetExtensionViews);
- } else if (name->Equals(v8::String::New("GetNextRequestId"))) {
- return v8::FunctionTemplate::New(GetNextRequestId);
- } else if (name->Equals(v8::String::New("OpenChannelToTab"))) {
- return v8::FunctionTemplate::New(OpenChannelToTab);
- } else if (name->Equals(v8::String::New("GetCurrentPageActions"))) {
- return v8::FunctionTemplate::New(GetCurrentPageActions);
- } else if (name->Equals(v8::String::New("StartRequest"))) {
- return v8::FunctionTemplate::New(StartRequest);
- } else if (name->Equals(v8::String::New("GetRenderViewId"))) {
- return v8::FunctionTemplate::New(GetRenderViewId);
- } else if (name->Equals(v8::String::New("GetPopupView"))) {
- return v8::FunctionTemplate::New(GetPopupView);
- } else if (name->Equals(v8::String::New("GetPopupParentWindow"))) {
- return v8::FunctionTemplate::New(GetPopupParentWindow);
- } else if (name->Equals(v8::String::New("SetExtensionActionIcon"))) {
- return v8::FunctionTemplate::New(SetExtensionActionIcon);
- } else if (name->Equals(v8::String::New("IsExtensionProcess"))) {
- return v8::FunctionTemplate::New(IsExtensionProcess);
- }
-
- return ExtensionBase::GetNativeFunction(name);
- }
-
- private:
- static v8::Handle<v8::Value> GetExtensionAPIDefinition(
- const v8::Arguments& args) {
- return v8::String::New(GetStringResource<IDR_EXTENSION_API_JSON>());
- }
-
- static v8::Handle<v8::Value> PopupViewFinder(
- const v8::Arguments& args,
- ViewType::Type viewtype_to_find) {
- // TODO(twiz) Correct the logic that ties the ownership of the pop-up view
- // to the hosting view. At the moment we assume that there may only be
- // a single pop-up view for a given extension. By doing so, we can find
- // the pop-up view by simply searching for the only pop-up view present.
- // We also assume that if the current view is a pop-up, we can find the
- // hosting view by searching for a TOOLSTRIP view.
- if (args.Length() != 0)
- return v8::Undefined();
-
- if (viewtype_to_find != ViewType::EXTENSION_POPUP &&
- viewtype_to_find != ViewType::EXTENSION_TOOLSTRIP) {
- NOTREACHED() << "Requesting invalid view type.";
- }
-
- // Disallow searching for a host view if we are a popup view, and likewise
- // if we are a toolstrip view.
- RenderView* render_view = bindings_utils::GetRenderViewForCurrentContext();
- if (!render_view ||
- render_view->view_type() == viewtype_to_find) {
- return v8::Undefined();
- }
-
- int browser_window_id = render_view->browser_window_id();
- std::string extension_id = ExtensionIdForCurrentContext();
- if (extension_id.empty())
- return v8::Undefined();
-
- ExtensionViewAccumulator popup_matcher(extension_id,
- browser_window_id,
- viewtype_to_find);
- RenderView::ForEach(&popup_matcher);
-
- if (0 == popup_matcher.views()->Length())
- return v8::Undefined();
- DCHECK(1 == popup_matcher.views()->Length());
-
- // Return the first view found.
- return popup_matcher.views()->Get(v8::Integer::New(0));
- }
-
- static v8::Handle<v8::Value> GetPopupView(const v8::Arguments& args) {
- return PopupViewFinder(args, ViewType::EXTENSION_POPUP);
- }
-
- static v8::Handle<v8::Value> GetPopupParentWindow(const v8::Arguments& args) {
- return PopupViewFinder(args, ViewType::EXTENSION_TOOLSTRIP);
- }
-
- static v8::Handle<v8::Value> GetExtensionViews(const v8::Arguments& args) {
- if (args.Length() != 2)
- return v8::Undefined();
-
- if (!args[0]->IsInt32() || !args[1]->IsString())
- return v8::Undefined();
-
- // |browser_window_id| == extension_misc::kUnknownWindowId means getting
- // views attached to any browser window.
- int browser_window_id = args[0]->Int32Value();
-
- std::string view_type_string = *v8::String::Utf8Value(args[1]->ToString());
- StringToUpperASCII(&view_type_string);
- // |view_type| == ViewType::INVALID means getting any type of views.
- ViewType::Type view_type = ViewType::INVALID;
- if (view_type_string == ViewType::kToolstrip) {
- view_type = ViewType::EXTENSION_TOOLSTRIP;
- } else if (view_type_string == ViewType::kMole) {
- view_type = ViewType::EXTENSION_MOLE;
- } else if (view_type_string == ViewType::kBackgroundPage) {
- view_type = ViewType::EXTENSION_BACKGROUND_PAGE;
- } else if (view_type_string == ViewType::kInfobar) {
- view_type = ViewType::EXTENSION_INFOBAR;
- } else if (view_type_string == ViewType::kNotification) {
- view_type = ViewType::NOTIFICATION;
- } else if (view_type_string == ViewType::kTabContents) {
- view_type = ViewType::TAB_CONTENTS;
- } else if (view_type_string == ViewType::kPopup) {
- view_type = ViewType::EXTENSION_POPUP;
- } else if (view_type_string != ViewType::kAll) {
- return v8::Undefined();
- }
-
- std::string extension_id = ExtensionIdForCurrentContext();
- if (extension_id.empty())
- return v8::Undefined();
-
- ExtensionViewAccumulator accumulator(extension_id, browser_window_id,
- view_type);
- RenderView::ForEach(&accumulator);
- return accumulator.views();
- }
-
- static v8::Handle<v8::Value> GetNextRequestId(const v8::Arguments& args) {
- static int next_request_id = 0;
- return v8::Integer::New(next_request_id++);
- }
-
- // Creates a new messaging channel to the tab with the given ID.
- static v8::Handle<v8::Value> OpenChannelToTab(const v8::Arguments& args) {
- // Get the current RenderView so that we can send a routed IPC message from
- // the correct source.
- RenderView* renderview = bindings_utils::GetRenderViewForCurrentContext();
- if (!renderview)
- return v8::Undefined();
-
- if (args.Length() >= 3 && args[0]->IsInt32() && args[1]->IsString() &&
- args[2]->IsString()) {
- int tab_id = args[0]->Int32Value();
- std::string extension_id = *v8::String::Utf8Value(args[1]->ToString());
- std::string channel_name = *v8::String::Utf8Value(args[2]->ToString());
- int port_id = -1;
- renderview->Send(new ViewHostMsg_OpenChannelToTab(
- renderview->routing_id(), tab_id, extension_id, channel_name,
- &port_id));
- return v8::Integer::New(port_id);
- }
- return v8::Undefined();
- }
-
- static v8::Handle<v8::Value> GetCurrentPageActions(
- const v8::Arguments& args) {
- std::string extension_id = *v8::String::Utf8Value(args[0]->ToString());
- PageActionIdMap* page_action_map = GetPageActionMap();
- PageActionIdMap::const_iterator it = page_action_map->find(extension_id);
-
- std::vector<std::string> page_actions;
- size_t size = 0;
- if (it != page_action_map->end()) {
- page_actions = it->second;
- size = page_actions.size();
- }
-
- v8::Local<v8::Array> page_action_vector = v8::Array::New(size);
- for (size_t i = 0; i < size; ++i) {
- std::string page_action_id = page_actions[i];
- page_action_vector->Set(v8::Integer::New(i),
- v8::String::New(page_action_id.c_str()));
- }
-
- return page_action_vector;
- }
-
- // Common code for starting an API request to the browser. |value_args|
- // contains the request's arguments.
- static v8::Handle<v8::Value> StartRequestCommon(
- const v8::Arguments& args, const ListValue& value_args) {
- // Get the current RenderView so that we can send a routed IPC message from
- // the correct source.
- RenderView* renderview = bindings_utils::GetRenderViewForCurrentContext();
- if (!renderview)
- return v8::Undefined();
-
- std::string name = *v8::String::AsciiValue(args[0]);
- if (GetFunctionNameSet()->find(name) == GetFunctionNameSet()->end()) {
- NOTREACHED() << "Unexpected function " << name;
- return v8::Undefined();
- }
-
- if (!ExtensionProcessBindings::CurrentContextHasPermission(name)) {
- return ExtensionProcessBindings::ThrowPermissionDeniedException(name);
- }
-
- GURL source_url;
- WebFrame* webframe = WebFrame::frameForCurrentContext();
- if (webframe)
- source_url = webframe->url();
-
- int request_id = args[2]->Int32Value();
- bool has_callback = args[3]->BooleanValue();
-
- v8::Persistent<v8::Context> current_context =
- v8::Persistent<v8::Context>::New(v8::Context::GetCurrent());
- DCHECK(!current_context.IsEmpty());
- GetPendingRequestMap()[request_id].reset(new PendingRequest(
- current_context, name));
-
- renderview->SendExtensionRequest(name, value_args, source_url,
- request_id, has_callback);
-
- return v8::Undefined();
- }
-
- // Starts an API request to the browser, with an optional callback. The
- // callback will be dispatched to EventBindings::HandleResponse.
- static v8::Handle<v8::Value> StartRequest(const v8::Arguments& args) {
- std::string str_args = *v8::String::Utf8Value(args[1]);
- base::JSONReader reader;
- scoped_ptr<Value> value_args;
- value_args.reset(reader.JsonToValue(str_args, false, false));
-
- // Since we do the serialization in the v8 extension, we should always get
- // valid JSON.
- if (!value_args.get() || !value_args->IsType(Value::TYPE_LIST)) {
- NOTREACHED() << "Invalid JSON passed to StartRequest.";
- return v8::Undefined();
- }
-
- return StartRequestCommon(args, static_cast<const ListValue&>(
- *value_args.get()));
- }
-
- // A special request for setting the extension action icon. This function
- // accepts a canvas ImageData object, so it needs to do extra processing
- // before sending the request to the browser.
- static v8::Handle<v8::Value> SetExtensionActionIcon(
- const v8::Arguments& args) {
- v8::Local<v8::Object> extension_args = args[1]->ToObject();
- v8::Local<v8::Object> details =
- extension_args->Get(v8::String::New("0"))->ToObject();
- v8::Local<v8::Object> image_data =
- details->Get(v8::String::New("imageData"))->ToObject();
- v8::Local<v8::Object> data =
- image_data->Get(v8::String::New("data"))->ToObject();
- int width = image_data->Get(v8::String::New("width"))->Int32Value();
- int height = image_data->Get(v8::String::New("height"))->Int32Value();
-
- int data_length = data->Get(v8::String::New("length"))->Int32Value();
- if (data_length != 4 * width * height) {
- NOTREACHED() << "Invalid argument to setIcon. Expecting ImageData.";
- return v8::Undefined();
- }
-
- SkBitmap bitmap;
- bitmap.setConfig(SkBitmap::kARGB_8888_Config, width, height);
- bitmap.allocPixels();
- bitmap.eraseARGB(0, 0, 0, 0);
-
- uint32_t* pixels = bitmap.getAddr32(0, 0);
- for (int t = 0; t < width*height; t++) {
- // |data| is RGBA, pixels is ARGB.
- pixels[t] = SkPreMultiplyColor(
- ((data->Get(v8::Integer::New(4*t + 3))->Int32Value() & 0xFF) << 24) |
- ((data->Get(v8::Integer::New(4*t + 0))->Int32Value() & 0xFF) << 16) |
- ((data->Get(v8::Integer::New(4*t + 1))->Int32Value() & 0xFF) << 8) |
- ((data->Get(v8::Integer::New(4*t + 2))->Int32Value() & 0xFF) << 0));
- }
-
- // Construct the Value object.
- IPC::Message bitmap_pickle;
- IPC::WriteParam(&bitmap_pickle, bitmap);
- Value* bitmap_value = BinaryValue::CreateWithCopiedBuffer(
- static_cast<const char*>(bitmap_pickle.data()), bitmap_pickle.size());
-
- DictionaryValue* dict = new DictionaryValue();
- dict->Set("imageData", bitmap_value);
-
- if (details->Has(v8::String::New("tabId"))) {
- dict->SetInteger("tabId",
- details->Get(v8::String::New("tabId"))->Int32Value());
- }
-
- ListValue list_value;
- list_value.Append(dict);
-
- return StartRequestCommon(args, list_value);
- }
-
- static v8::Handle<v8::Value> GetRenderViewId(const v8::Arguments& args) {
- RenderView* renderview = bindings_utils::GetRenderViewForCurrentContext();
- if (!renderview)
- return v8::Undefined();
- return v8::Integer::New(renderview->routing_id());
- }
-
- static v8::Handle<v8::Value> IsExtensionProcess(const v8::Arguments& args) {
- bool retval = false;
- if (EventBindings::GetRenderThread())
- retval = EventBindings::GetRenderThread()->IsExtensionProcess();
- return v8::Boolean::New(retval);
- }
-};
-
-} // namespace
-
-v8::Extension* ExtensionProcessBindings::Get() {
- static v8::Extension* extension = new ExtensionImpl();
- return extension;
-}
-
-void ExtensionProcessBindings::GetActiveExtensions(
- std::set<std::string>* extension_ids) {
- GetActiveExtensionIDs(extension_ids);
-}
-
-void ExtensionProcessBindings::SetFunctionNames(
- const std::vector<std::string>& names) {
- ExtensionImpl::SetFunctionNames(names);
-}
-
-void ExtensionProcessBindings::SetIncognitoEnabled(
- const std::string& extension_id, bool enabled) {
- (*GetIncognitoEnabledMap())[extension_id] = enabled;
-}
-
-// static
-bool ExtensionProcessBindings::HasIncognitoEnabled(
- const std::string& extension_id) {
- return (!extension_id.empty() && (*GetIncognitoEnabledMap())[extension_id]);
-}
-
-// static
-void ExtensionProcessBindings::HandleResponse(int request_id, bool success,
- const std::string& response,
- const std::string& error) {
- PendingRequestMap& pending_requests = GetPendingRequestMap();
- PendingRequestMap::iterator request = pending_requests.find(request_id);
- if (request == pending_requests.end())
- return; // The frame went away.
-
- v8::HandleScope handle_scope;
- v8::Handle<v8::Value> argv[5];
- argv[0] = v8::Integer::New(request_id);
- argv[1] = v8::String::New(request->second->name.c_str());
- argv[2] = v8::Boolean::New(success);
- argv[3] = v8::String::New(response.c_str());
- argv[4] = v8::String::New(error.c_str());
- v8::Handle<v8::Value> retval = bindings_utils::CallFunctionInContext(
- request->second->context, "handleResponse", arraysize(argv), argv);
- // In debug, the js will validate the callback parameters and return a
- // string if a validation error has occured.
-#ifdef _DEBUG
- if (!retval.IsEmpty() && !retval->IsUndefined()) {
- std::string error = *v8::String::AsciiValue(retval);
- DCHECK(false) << error;
- }
-#endif
-
- request->second->context.Dispose();
- request->second->context.Clear();
- pending_requests.erase(request);
-}
-
-// static
-void ExtensionProcessBindings::SetPageActions(
- const std::string& extension_id,
- const std::vector<std::string>& page_actions) {
- PageActionIdMap& page_action_map = *GetPageActionMap();
- if (!page_actions.empty()) {
- page_action_map[extension_id] = page_actions;
- } else {
- if (page_action_map.find(extension_id) != page_action_map.end())
- page_action_map.erase(extension_id);
- }
-}
-
-// static
-void ExtensionProcessBindings::SetAPIPermissions(
- const std::string& extension_id,
- const std::vector<std::string>& permissions) {
- PermissionsMap& permissions_map = *GetPermissionsMap(extension_id);
-
- // Default all the API permissions to off. We will reset them below.
- for (size_t i = 0; i < Extension::kNumPermissions; ++i)
- permissions_map[Extension::kPermissionNames[i]] = false;
- for (size_t i = 0; i < permissions.size(); ++i)
- permissions_map[permissions[i]] = true;
-}
-
-// static
-void ExtensionProcessBindings::SetHostPermissions(
- const GURL& extension_url,
- const std::vector<URLPattern>& permissions) {
- for (size_t i = 0; i < permissions.size(); ++i) {
- const char* schemes[] = {
- chrome::kHttpScheme,
- chrome::kHttpsScheme,
- chrome::kFileScheme,
- chrome::kChromeUIScheme,
- };
- for (size_t j = 0; j < arraysize(schemes); ++j) {
- if (permissions[i].MatchesScheme(schemes[j])) {
- WebSecurityPolicy::addOriginAccessWhitelistEntry(
- extension_url,
- WebKit::WebString::fromUTF8(schemes[j]),
- WebKit::WebString::fromUTF8(permissions[i].host()),
- permissions[i].match_subdomains());
- }
- }
- }
-}
-
-// static
-bool ExtensionProcessBindings::CurrentContextHasPermission(
- const std::string& function_name) {
- std::string extension_id = ExtensionImpl::ExtensionIdForCurrentContext();
- return HasPermission(extension_id, function_name);
-}
-
-// static
-bool ExtensionProcessBindings::HasPermission(const std::string& extension_id,
- const std::string& permission) {
- std::string permission_name = permission;
-
- // See if this is a function or event name first and strip out the package.
- // Functions will be of the form package.function
- // Events will be of the form package/id or package.optional.stuff
- size_t separator = permission.find_first_of("./");
- if (separator != std::string::npos)
- permission_name = permission.substr(0, separator);
-
- // windows and tabs are the same permission.
- if (permission_name == "windows")
- permission_name = Extension::kTabPermission;
-
- for (size_t i = 0; i < arraysize(kNonPermissionExtensionPackages); ++i)
- if (permission_name == kNonPermissionExtensionPackages[i])
- return true;
-
- PermissionsMap& permissions_map = *GetPermissionsMap(extension_id);
- PermissionsMap::iterator it = permissions_map.find(permission_name);
- return (it != permissions_map.end() && it->second);
-}
-
-// static
-v8::Handle<v8::Value>
- ExtensionProcessBindings::ThrowPermissionDeniedException(
- const std::string& function_name) {
- static const char kMessage[] =
- "You do not have permission to use '%s'. Be sure to declare"
- " in your manifest what permissions you need.";
- std::string error_msg = StringPrintf(kMessage, function_name.c_str());
-
- return v8::ThrowException(v8::Exception::Error(
- v8::String::New(error_msg.c_str())));
-}
-
-// static
-void ExtensionProcessBindings::SetViewType(WebView* view,
- ViewType::Type type) {
- DCHECK(type == ViewType::EXTENSION_MOLE ||
- type == ViewType::EXTENSION_TOOLSTRIP);
- const char* type_str;
- if (type == ViewType::EXTENSION_MOLE)
- type_str = "mole";
- else if (type == ViewType::EXTENSION_TOOLSTRIP)
- type_str = "toolstrip";
- else
- return;
-
- v8::HandleScope handle_scope;
- WebFrame* frame = view->mainFrame();
- v8::Local<v8::Context> context = frame->mainWorldScriptContext();
- v8::Handle<v8::Value> argv[1];
- argv[0] = v8::String::New(type_str);
- bindings_utils::CallFunctionInContext(context, "setViewType",
- arraysize(argv), argv);
-}
+// Copyright (c) 2010 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/extensions/extension_process_bindings.h"
+
+#include <map>
+#include <set>
+#include <string>
+#include <vector>
+
+#include "base/command_line.h"
+#include "base/json/json_reader.h"
+#include "base/scoped_ptr.h"
+#include "base/singleton.h"
+#include "base/string_util.h"
+#include "chrome/common/chrome_switches.h"
+#include "chrome/common/extensions/extension.h"
+#include "chrome/common/extensions/extension_constants.h"
+#include "chrome/common/extensions/url_pattern.h"
+#include "chrome/common/render_messages.h"
+#include "chrome/common/url_constants.h"
+#include "chrome/renderer/extensions/bindings_utils.h"
+#include "chrome/renderer/extensions/event_bindings.h"
+#include "chrome/renderer/extensions/js_only_v8_extensions.h"
+#include "chrome/renderer/extensions/renderer_extension_bindings.h"
+#include "chrome/renderer/user_script_slave.h"
+#include "chrome/renderer/render_thread.h"
+#include "chrome/renderer/render_view.h"
+#include "chrome/renderer/render_view_visitor.h"
+#include "grit/common_resources.h"
+#include "grit/renderer_resources.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+#include "third_party/skia/include/core/SkColor.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebFrame.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebURL.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebKit.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebSecurityPolicy.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebView.h"
+
+using bindings_utils::GetStringResource;
+using bindings_utils::ContextInfo;
+using bindings_utils::ContextList;
+using bindings_utils::GetContexts;
+using bindings_utils::GetPendingRequestMap;
+using bindings_utils::PendingRequest;
+using bindings_utils::PendingRequestMap;
+using bindings_utils::ExtensionBase;
+using WebKit::WebFrame;
+using WebKit::WebSecurityPolicy;
+using WebKit::WebView;
+
+namespace {
+
+// A map of extension ID to vector of page action ids.
+typedef std::map< std::string, std::vector<std::string> > PageActionIdMap;
+
+// A map of permission name to whether its enabled for this extension.
+typedef std::map<std::string, bool> PermissionsMap;
+
+// A map of extension ID to permissions map.
+typedef std::map<std::string, PermissionsMap> ExtensionPermissionsMap;
+
+// A map of extension ID to whether this extension was enabled in incognito.
+typedef std::map<std::string, bool> IncognitoEnabledMap;
+
+const char kExtensionName[] = "chrome/ExtensionProcessBindings";
+const char* kExtensionDeps[] = {
+ BaseJsV8Extension::kName,
+ EventBindings::kName,
+ JsonSchemaJsV8Extension::kName,
+ RendererExtensionBindings::kName,
+ ExtensionApiTestV8Extension::kName,
+};
+
+// A list of the API packages which have no associated permission.
+// TODO(erikkay) It might be nice if for consistency we could merge these with
+// the permissions list, or at least have them in one place.
+const char* kNonPermissionExtensionPackages[] = {
+ "extension",
+ // TODO(erikkay): We're inconsistent about the the package name in the events
+ // for pageAction and browserAction.
+ "pageAction",
+ "pageActions",
+ "browserAction",
+ "browserActions",
+ "i18n",
+ "devtools",
+ "test"
+};
+
+struct SingletonData {
+ std::set<std::string> function_names_;
+ PageActionIdMap page_action_ids_;
+ ExtensionPermissionsMap permissions_;
+ IncognitoEnabledMap incognito_enabled_map_;
+};
+
+static std::set<std::string>* GetFunctionNameSet() {
+ return &Singleton<SingletonData>()->function_names_;
+}
+
+static PageActionIdMap* GetPageActionMap() {
+ return &Singleton<SingletonData>()->page_action_ids_;
+}
+
+static PermissionsMap* GetPermissionsMap(const std::string& extension_id) {
+ return &Singleton<SingletonData>()->permissions_[extension_id];
+}
+
+static IncognitoEnabledMap* GetIncognitoEnabledMap() {
+ return &Singleton<SingletonData>()->incognito_enabled_map_;
+}
+
+static void GetActiveExtensionIDs(std::set<std::string>* extension_ids) {
+ ExtensionPermissionsMap& permissions =
+ Singleton<SingletonData>()->permissions_;
+
+ for (ExtensionPermissionsMap::iterator iter = permissions.begin();
+ iter != permissions.end(); ++iter) {
+ extension_ids->insert(iter->first);
+ }
+}
+
+// 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 ExtensionViewAccumulator : public RenderViewVisitor {
+ public:
+ ExtensionViewAccumulator(const std::string& extension_id,
+ int browser_window_id,
+ ViewType::Type view_type)
+ : extension_id_(extension_id),
+ browser_window_id_(browser_window_id),
+ view_type_(view_type),
+ views_(v8::Array::New()),
+ index_(0) {
+ }
+
+ v8::Local<v8::Array> views() { return views_; }
+
+ virtual bool Visit(RenderView* render_view) {
+ if (!ViewTypeMatches(render_view->view_type(), view_type_))
+ return true;
+
+ GURL url = render_view->webview()->mainFrame()->url();
+ if (!url.SchemeIs(chrome::kExtensionScheme))
+ return true;
+ const std::string& extension_id = url.host();
+ if (extension_id != extension_id_)
+ return true;
+
+ // If we are searching for a pop-up, it may be the case that the pop-up
+ // is not attached to a browser window instance. (It is hosted in a
+ // ExternalTabContainer.) If so, then bypass validation of
+ // same-browser-window origin.
+ // TODO(twiz): The browser window id of the views visited should always
+ // match that of the arguments to the accumulator.
+ // See bug: http://crbug.com/29646
+ if (!(view_type_ == ViewType::EXTENSION_POPUP &&
+ render_view->browser_window_id() ==
+ extension_misc::kUnknownWindowId)) {
+ if (browser_window_id_ != extension_misc::kUnknownWindowId &&
+ render_view->browser_window_id() != browser_window_id_) {
+ return true;
+ }
+ }
+
+ v8::Local<v8::Context> context =
+ render_view->webview()->mainFrame()->mainWorldScriptContext();
+ if (!context.IsEmpty()) {
+ v8::Local<v8::Value> window = context->Global();
+ DCHECK(!window.IsEmpty());
+
+ if (!OnMatchedView(window))
+ return false;
+ }
+ return true;
+ }
+
+ private:
+ // Called on each view found matching the search criteria. Returns false
+ // to terminate the iteration.
+ bool OnMatchedView(const v8::Local<v8::Value>& view_window) {
+ views_->Set(v8::Integer::New(index_), view_window);
+ index_++;
+
+ if (view_type_ == ViewType::EXTENSION_BACKGROUND_PAGE)
+ return false; // There can be only one...
+
+ return true;
+ }
+
+ // Returns true is |type| "isa" |match|.
+ static bool ViewTypeMatches(ViewType::Type type, ViewType::Type match) {
+ if (type == match)
+ return true;
+
+ // INVALID means match all.
+ if (match == ViewType::INVALID)
+ return true;
+
+ return false;
+ }
+
+ std::string extension_id_;
+ int browser_window_id_;
+ ViewType::Type view_type_;
+ v8::Local<v8::Array> views_;
+ int index_;
+};
+
+class ExtensionImpl : public ExtensionBase {
+ public:
+ ExtensionImpl() : ExtensionBase(
+ kExtensionName, GetStringResource<IDR_EXTENSION_PROCESS_BINDINGS_JS>(),
+ arraysize(kExtensionDeps), kExtensionDeps) {}
+
+ static void SetFunctionNames(const std::vector<std::string>& names) {
+ std::set<std::string>* name_set = GetFunctionNameSet();
+ for (size_t i = 0; i < names.size(); ++i) {
+ name_set->insert(names[i]);
+ }
+ }
+
+ // Note: do not call this function before or during the chromeHidden.onLoad
+ // event dispatch. The URL might not have been committed yet and might not
+ // be an extension URL.
+ static std::string ExtensionIdForCurrentContext() {
+ RenderView* renderview = bindings_utils::GetRenderViewForCurrentContext();
+ if (!renderview)
+ return std::string(); // this can happen as a tab is closing.
+
+ GURL url = renderview->webview()->mainFrame()->url();
+ if (!url.SchemeIs(chrome::kExtensionScheme))
+ return std::string();
+
+ return url.host();
+ }
+
+ virtual v8::Handle<v8::FunctionTemplate> GetNativeFunction(
+ v8::Handle<v8::String> name) {
+ if (name->Equals(v8::String::New("GetExtensionAPIDefinition"))) {
+ return v8::FunctionTemplate::New(GetExtensionAPIDefinition);
+ } else if (name->Equals(v8::String::New("GetExtensionViews"))) {
+ return v8::FunctionTemplate::New(GetExtensionViews);
+ } else if (name->Equals(v8::String::New("GetNextRequestId"))) {
+ return v8::FunctionTemplate::New(GetNextRequestId);
+ } else if (name->Equals(v8::String::New("OpenChannelToTab"))) {
+ return v8::FunctionTemplate::New(OpenChannelToTab);
+ } else if (name->Equals(v8::String::New("GetCurrentPageActions"))) {
+ return v8::FunctionTemplate::New(GetCurrentPageActions);
+ } else if (name->Equals(v8::String::New("StartRequest"))) {
+ return v8::FunctionTemplate::New(StartRequest);
+ } else if (name->Equals(v8::String::New("GetRenderViewId"))) {
+ return v8::FunctionTemplate::New(GetRenderViewId);
+ } else if (name->Equals(v8::String::New("GetPopupView"))) {
+ return v8::FunctionTemplate::New(GetPopupView);
+ } else if (name->Equals(v8::String::New("GetPopupParentWindow"))) {
+ return v8::FunctionTemplate::New(GetPopupParentWindow);
+ } else if (name->Equals(v8::String::New("SetExtensionActionIcon"))) {
+ return v8::FunctionTemplate::New(SetExtensionActionIcon);
+ } else if (name->Equals(v8::String::New("IsExtensionProcess"))) {
+ return v8::FunctionTemplate::New(IsExtensionProcess);
+ }
+
+ return ExtensionBase::GetNativeFunction(name);
+ }
+
+ private:
+ static v8::Handle<v8::Value> GetExtensionAPIDefinition(
+ const v8::Arguments& args) {
+ return v8::String::New(GetStringResource<IDR_EXTENSION_API_JSON>());
+ }
+
+ static v8::Handle<v8::Value> PopupViewFinder(
+ const v8::Arguments& args,
+ ViewType::Type viewtype_to_find) {
+ // TODO(twiz) Correct the logic that ties the ownership of the pop-up view
+ // to the hosting view. At the moment we assume that there may only be
+ // a single pop-up view for a given extension. By doing so, we can find
+ // the pop-up view by simply searching for the only pop-up view present.
+ // We also assume that if the current view is a pop-up, we can find the
+ // hosting view by searching for a tab contents view.
+ if (args.Length() != 0)
+ return v8::Undefined();
+
+ if (viewtype_to_find != ViewType::EXTENSION_POPUP &&
+ viewtype_to_find != ViewType::TAB_CONTENTS) {
+ NOTREACHED() << "Requesting invalid view type.";
+ }
+
+ // Disallow searching for the same view type as the current view:
+ // Popups can only look for hosts, and hosts can only look for popups.
+ RenderView* render_view = bindings_utils::GetRenderViewForCurrentContext();
+ if (!render_view ||
+ render_view->view_type() == viewtype_to_find) {
+ return v8::Undefined();
+ }
+
+ int browser_window_id = render_view->browser_window_id();
+ std::string extension_id = ExtensionIdForCurrentContext();
+ if (extension_id.empty())
+ return v8::Undefined();
+
+ ExtensionViewAccumulator popup_matcher(extension_id,
+ browser_window_id,
+ viewtype_to_find);
+ RenderView::ForEach(&popup_matcher);
+
+ if (0 == popup_matcher.views()->Length())
+ return v8::Undefined();
+ DCHECK(1 == popup_matcher.views()->Length());
+
+ // Return the first view found.
+ return popup_matcher.views()->Get(v8::Integer::New(0));
+ }
+
+ static v8::Handle<v8::Value> GetPopupView(const v8::Arguments& args) {
+ return PopupViewFinder(args, ViewType::EXTENSION_POPUP);
+ }
+
+ static v8::Handle<v8::Value> GetPopupParentWindow(const v8::Arguments& args) {
+ return PopupViewFinder(args, ViewType::TAB_CONTENTS);
+ }
+
+ static v8::Handle<v8::Value> GetExtensionViews(const v8::Arguments& args) {
+ if (args.Length() != 2)
+ return v8::Undefined();
+
+ if (!args[0]->IsInt32() || !args[1]->IsString())
+ return v8::Undefined();
+
+ // |browser_window_id| == extension_misc::kUnknownWindowId means getting
+ // views attached to any browser window.
+ int browser_window_id = args[0]->Int32Value();
+
+ std::string view_type_string = *v8::String::Utf8Value(args[1]->ToString());
+ StringToUpperASCII(&view_type_string);
+ // |view_type| == ViewType::INVALID means getting any type of views.
+ ViewType::Type view_type = ViewType::INVALID;
+ if (view_type_string == ViewType::kBackgroundPage) {
+ view_type = ViewType::EXTENSION_BACKGROUND_PAGE;
+ } else if (view_type_string == ViewType::kInfobar) {
+ view_type = ViewType::EXTENSION_INFOBAR;
+ } else if (view_type_string == ViewType::kNotification) {
+ view_type = ViewType::NOTIFICATION;
+ } else if (view_type_string == ViewType::kTabContents) {
+ view_type = ViewType::TAB_CONTENTS;
+ } else if (view_type_string == ViewType::kPopup) {
+ view_type = ViewType::EXTENSION_POPUP;
+ } else if (view_type_string != ViewType::kAll) {
+ return v8::Undefined();
+ }
+
+ std::string extension_id = ExtensionIdForCurrentContext();
+ if (extension_id.empty())
+ return v8::Undefined();
+
+ ExtensionViewAccumulator accumulator(extension_id, browser_window_id,
+ view_type);
+ RenderView::ForEach(&accumulator);
+ return accumulator.views();
+ }
+
+ static v8::Handle<v8::Value> GetNextRequestId(const v8::Arguments& args) {
+ static int next_request_id = 0;
+ return v8::Integer::New(next_request_id++);
+ }
+
+ // Creates a new messaging channel to the tab with the given ID.
+ static v8::Handle<v8::Value> OpenChannelToTab(const v8::Arguments& args) {
+ // Get the current RenderView so that we can send a routed IPC message from
+ // the correct source.
+ RenderView* renderview = bindings_utils::GetRenderViewForCurrentContext();
+ if (!renderview)
+ return v8::Undefined();
+
+ if (args.Length() >= 3 && args[0]->IsInt32() && args[1]->IsString() &&
+ args[2]->IsString()) {
+ int tab_id = args[0]->Int32Value();
+ std::string extension_id = *v8::String::Utf8Value(args[1]->ToString());
+ std::string channel_name = *v8::String::Utf8Value(args[2]->ToString());
+ int port_id = -1;
+ renderview->Send(new ViewHostMsg_OpenChannelToTab(
+ renderview->routing_id(), tab_id, extension_id, channel_name,
+ &port_id));
+ return v8::Integer::New(port_id);
+ }
+ return v8::Undefined();
+ }
+
+ static v8::Handle<v8::Value> GetCurrentPageActions(
+ const v8::Arguments& args) {
+ std::string extension_id = *v8::String::Utf8Value(args[0]->ToString());
+ PageActionIdMap* page_action_map = GetPageActionMap();
+ PageActionIdMap::const_iterator it = page_action_map->find(extension_id);
+
+ std::vector<std::string> page_actions;
+ size_t size = 0;
+ if (it != page_action_map->end()) {
+ page_actions = it->second;
+ size = page_actions.size();
+ }
+
+ v8::Local<v8::Array> page_action_vector = v8::Array::New(size);
+ for (size_t i = 0; i < size; ++i) {
+ std::string page_action_id = page_actions[i];
+ page_action_vector->Set(v8::Integer::New(i),
+ v8::String::New(page_action_id.c_str()));
+ }
+
+ return page_action_vector;
+ }
+
+ // Common code for starting an API request to the browser. |value_args|
+ // contains the request's arguments.
+ static v8::Handle<v8::Value> StartRequestCommon(
+ const v8::Arguments& args, const ListValue& value_args) {
+ // Get the current RenderView so that we can send a routed IPC message from
+ // the correct source.
+ RenderView* renderview = bindings_utils::GetRenderViewForCurrentContext();
+ if (!renderview)
+ return v8::Undefined();
+
+ std::string name = *v8::String::AsciiValue(args[0]);
+ if (GetFunctionNameSet()->find(name) == GetFunctionNameSet()->end()) {
+ NOTREACHED() << "Unexpected function " << name;
+ return v8::Undefined();
+ }
+
+ if (!ExtensionProcessBindings::CurrentContextHasPermission(name)) {
+ return ExtensionProcessBindings::ThrowPermissionDeniedException(name);
+ }
+
+ GURL source_url;
+ WebFrame* webframe = WebFrame::frameForCurrentContext();
+ if (webframe)
+ source_url = webframe->url();
+
+ int request_id = args[2]->Int32Value();
+ bool has_callback = args[3]->BooleanValue();
+
+ v8::Persistent<v8::Context> current_context =
+ v8::Persistent<v8::Context>::New(v8::Context::GetCurrent());
+ DCHECK(!current_context.IsEmpty());
+ GetPendingRequestMap()[request_id].reset(new PendingRequest(
+ current_context, name));
+
+ renderview->SendExtensionRequest(name, value_args, source_url,
+ request_id, has_callback);
+
+ return v8::Undefined();
+ }
+
+ // Starts an API request to the browser, with an optional callback. The
+ // callback will be dispatched to EventBindings::HandleResponse.
+ static v8::Handle<v8::Value> StartRequest(const v8::Arguments& args) {
+ std::string str_args = *v8::String::Utf8Value(args[1]);
+ base::JSONReader reader;
+ scoped_ptr<Value> value_args;
+ value_args.reset(reader.JsonToValue(str_args, false, false));
+
+ // Since we do the serialization in the v8 extension, we should always get
+ // valid JSON.
+ if (!value_args.get() || !value_args->IsType(Value::TYPE_LIST)) {
+ NOTREACHED() << "Invalid JSON passed to StartRequest.";
+ return v8::Undefined();
+ }
+
+ return StartRequestCommon(args, static_cast<const ListValue&>(
+ *value_args.get()));
+ }
+
+ // A special request for setting the extension action icon. This function
+ // accepts a canvas ImageData object, so it needs to do extra processing
+ // before sending the request to the browser.
+ static v8::Handle<v8::Value> SetExtensionActionIcon(
+ const v8::Arguments& args) {
+ v8::Local<v8::Object> extension_args = args[1]->ToObject();
+ v8::Local<v8::Object> details =
+ extension_args->Get(v8::String::New("0"))->ToObject();
+ v8::Local<v8::Object> image_data =
+ details->Get(v8::String::New("imageData"))->ToObject();
+ v8::Local<v8::Object> data =
+ image_data->Get(v8::String::New("data"))->ToObject();
+ int width = image_data->Get(v8::String::New("width"))->Int32Value();
+ int height = image_data->Get(v8::String::New("height"))->Int32Value();
+
+ int data_length = data->Get(v8::String::New("length"))->Int32Value();
+ if (data_length != 4 * width * height) {
+ NOTREACHED() << "Invalid argument to setIcon. Expecting ImageData.";
+ return v8::Undefined();
+ }
+
+ SkBitmap bitmap;
+ bitmap.setConfig(SkBitmap::kARGB_8888_Config, width, height);
+ bitmap.allocPixels();
+ bitmap.eraseARGB(0, 0, 0, 0);
+
+ uint32_t* pixels = bitmap.getAddr32(0, 0);
+ for (int t = 0; t < width*height; t++) {
+ // |data| is RGBA, pixels is ARGB.
+ pixels[t] = SkPreMultiplyColor(
+ ((data->Get(v8::Integer::New(4*t + 3))->Int32Value() & 0xFF) << 24) |
+ ((data->Get(v8::Integer::New(4*t + 0))->Int32Value() & 0xFF) << 16) |
+ ((data->Get(v8::Integer::New(4*t + 1))->Int32Value() & 0xFF) << 8) |
+ ((data->Get(v8::Integer::New(4*t + 2))->Int32Value() & 0xFF) << 0));
+ }
+
+ // Construct the Value object.
+ IPC::Message bitmap_pickle;
+ IPC::WriteParam(&bitmap_pickle, bitmap);
+ Value* bitmap_value = BinaryValue::CreateWithCopiedBuffer(
+ static_cast<const char*>(bitmap_pickle.data()), bitmap_pickle.size());
+
+ DictionaryValue* dict = new DictionaryValue();
+ dict->Set("imageData", bitmap_value);
+
+ if (details->Has(v8::String::New("tabId"))) {
+ dict->SetInteger("tabId",
+ details->Get(v8::String::New("tabId"))->Int32Value());
+ }
+
+ ListValue list_value;
+ list_value.Append(dict);
+
+ return StartRequestCommon(args, list_value);
+ }
+
+ static v8::Handle<v8::Value> GetRenderViewId(const v8::Arguments& args) {
+ RenderView* renderview = bindings_utils::GetRenderViewForCurrentContext();
+ if (!renderview)
+ return v8::Undefined();
+ return v8::Integer::New(renderview->routing_id());
+ }
+
+ static v8::Handle<v8::Value> IsExtensionProcess(const v8::Arguments& args) {
+ bool retval = false;
+ if (EventBindings::GetRenderThread())
+ retval = EventBindings::GetRenderThread()->IsExtensionProcess();
+ return v8::Boolean::New(retval);
+ }
+};
+
+} // namespace
+
+v8::Extension* ExtensionProcessBindings::Get() {
+ static v8::Extension* extension = new ExtensionImpl();
+ return extension;
+}
+
+void ExtensionProcessBindings::GetActiveExtensions(
+ std::set<std::string>* extension_ids) {
+ GetActiveExtensionIDs(extension_ids);
+}
+
+void ExtensionProcessBindings::SetFunctionNames(
+ const std::vector<std::string>& names) {
+ ExtensionImpl::SetFunctionNames(names);
+}
+
+void ExtensionProcessBindings::SetIncognitoEnabled(
+ const std::string& extension_id, bool enabled) {
+ (*GetIncognitoEnabledMap())[extension_id] = enabled;
+}
+
+// static
+bool ExtensionProcessBindings::HasIncognitoEnabled(
+ const std::string& extension_id) {
+ return (!extension_id.empty() && (*GetIncognitoEnabledMap())[extension_id]);
+}
+
+// static
+void ExtensionProcessBindings::HandleResponse(int request_id, bool success,
+ const std::string& response,
+ const std::string& error) {
+ PendingRequestMap& pending_requests = GetPendingRequestMap();
+ PendingRequestMap::iterator request = pending_requests.find(request_id);
+ if (request == pending_requests.end())
+ return; // The frame went away.
+
+ v8::HandleScope handle_scope;
+ v8::Handle<v8::Value> argv[5];
+ argv[0] = v8::Integer::New(request_id);
+ argv[1] = v8::String::New(request->second->name.c_str());
+ argv[2] = v8::Boolean::New(success);
+ argv[3] = v8::String::New(response.c_str());
+ argv[4] = v8::String::New(error.c_str());
+ v8::Handle<v8::Value> retval = bindings_utils::CallFunctionInContext(
+ request->second->context, "handleResponse", arraysize(argv), argv);
+ // In debug, the js will validate the callback parameters and return a
+ // string if a validation error has occured.
+#ifdef _DEBUG
+ if (!retval.IsEmpty() && !retval->IsUndefined()) {
+ std::string error = *v8::String::AsciiValue(retval);
+ DCHECK(false) << error;
+ }
+#endif
+
+ request->second->context.Dispose();
+ request->second->context.Clear();
+ pending_requests.erase(request);
+}
+
+// static
+void ExtensionProcessBindings::SetPageActions(
+ const std::string& extension_id,
+ const std::vector<std::string>& page_actions) {
+ PageActionIdMap& page_action_map = *GetPageActionMap();
+ if (!page_actions.empty()) {
+ page_action_map[extension_id] = page_actions;
+ } else {
+ if (page_action_map.find(extension_id) != page_action_map.end())
+ page_action_map.erase(extension_id);
+ }
+}
+
+// static
+void ExtensionProcessBindings::SetAPIPermissions(
+ const std::string& extension_id,
+ const std::vector<std::string>& permissions) {
+ PermissionsMap& permissions_map = *GetPermissionsMap(extension_id);
+
+ // Default all the API permissions to off. We will reset them below.
+ for (size_t i = 0; i < Extension::kNumPermissions; ++i)
+ permissions_map[Extension::kPermissionNames[i]] = false;
+ for (size_t i = 0; i < permissions.size(); ++i)
+ permissions_map[permissions[i]] = true;
+}
+
+// static
+void ExtensionProcessBindings::SetHostPermissions(
+ const GURL& extension_url,
+ const std::vector<URLPattern>& permissions) {
+ for (size_t i = 0; i < permissions.size(); ++i) {
+ const char* schemes[] = {
+ chrome::kHttpScheme,
+ chrome::kHttpsScheme,
+ chrome::kFileScheme,
+ chrome::kChromeUIScheme,
+ };
+ for (size_t j = 0; j < arraysize(schemes); ++j) {
+ if (permissions[i].MatchesScheme(schemes[j])) {
+ WebSecurityPolicy::addOriginAccessWhitelistEntry(
+ extension_url,
+ WebKit::WebString::fromUTF8(schemes[j]),
+ WebKit::WebString::fromUTF8(permissions[i].host()),
+ permissions[i].match_subdomains());
+ }
+ }
+ }
+}
+
+// static
+bool ExtensionProcessBindings::CurrentContextHasPermission(
+ const std::string& function_name) {
+ std::string extension_id = ExtensionImpl::ExtensionIdForCurrentContext();
+ return HasPermission(extension_id, function_name);
+}
+
+// static
+bool ExtensionProcessBindings::HasPermission(const std::string& extension_id,
+ const std::string& permission) {
+ std::string permission_name = permission;
+
+ // See if this is a function or event name first and strip out the package.
+ // Functions will be of the form package.function
+ // Events will be of the form package/id or package.optional.stuff
+ size_t separator = permission.find_first_of("./");
+ if (separator != std::string::npos)
+ permission_name = permission.substr(0, separator);
+
+ // windows and tabs are the same permission.
+ if (permission_name == "windows")
+ permission_name = Extension::kTabPermission;
+
+ for (size_t i = 0; i < arraysize(kNonPermissionExtensionPackages); ++i)
+ if (permission_name == kNonPermissionExtensionPackages[i])
+ return true;
+
+ PermissionsMap& permissions_map = *GetPermissionsMap(extension_id);
+ PermissionsMap::iterator it = permissions_map.find(permission_name);
+ return (it != permissions_map.end() && it->second);
+}
+
+// static
+v8::Handle<v8::Value>
+ ExtensionProcessBindings::ThrowPermissionDeniedException(
+ const std::string& function_name) {
+ static const char kMessage[] =
+ "You do not have permission to use '%s'. Be sure to declare"
+ " in your manifest what permissions you need.";
+ std::string error_msg = StringPrintf(kMessage, function_name.c_str());
+
+ return v8::ThrowException(v8::Exception::Error(
+ v8::String::New(error_msg.c_str())));
+}
+
diff --git a/chrome/renderer/extensions/extension_process_bindings.h b/chrome/renderer/extensions/extension_process_bindings.h
index 2710901..d64b4255 100644
--- a/chrome/renderer/extensions/extension_process_bindings.h
+++ b/chrome/renderer/extensions/extension_process_bindings.h
@@ -71,11 +71,6 @@ class ExtensionProcessBindings {
// denied. Must be called with a valid V8 context in scope.
static v8::Handle<v8::Value> ThrowPermissionDeniedException(
const std::string& function_name);
-
- // For EXTENSION_* |type| values, adds/replaces a special class name on to
- // the document element (e.g. "extension_toolstrip", "extension_mole") so
- // that the page can use CSS rules to control its display appropriately.
- static void SetViewType(WebKit::WebView* view, ViewType::Type type);
};
#endif // CHROME_RENDERER_EXTENSIONS_EXTENSION_PROCESS_BINDINGS_H_