diff options
author | erikkay@chromium.org <erikkay@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-08-12 20:12:42 +0000 |
---|---|---|
committer | erikkay@chromium.org <erikkay@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-08-12 20:12:42 +0000 |
commit | 6d7a6046d581348565fc0634d81efce653a1f550 (patch) | |
tree | d7f2b7ca49c1805d11dea9751adea02a0562a939 /chrome/renderer/extensions | |
parent | 0ba9330a17a3fd294a28972f5a81b64f550e6a20 (diff) | |
download | chromium_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.cc | 1432 | ||||
-rw-r--r-- | chrome/renderer/extensions/extension_process_bindings.h | 5 |
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_ |