| OLD | NEW |
| 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include <map> | 5 #include <map> |
| 6 #include <set> | 6 #include <set> |
| 7 #include <string> | 7 #include <string> |
| 8 #include <vector> | 8 #include <vector> |
| 9 | 9 |
| 10 #include "chrome/renderer/extensions/extension_process_bindings.h" | 10 #include "chrome/renderer/extensions/extension_process_bindings.h" |
| 11 | 11 |
| 12 #include "base/json_reader.h" | 12 #include "base/json_reader.h" |
| 13 #include "base/singleton.h" | 13 #include "base/singleton.h" |
| 14 #include "chrome/common/extensions/extension.h" | 14 #include "chrome/common/extensions/extension.h" |
| 15 #include "chrome/common/extensions/extension_message_bundle.h" | 15 #include "chrome/common/extensions/extension_message_bundle.h" |
| 16 #include "chrome/common/extensions/url_pattern.h" | 16 #include "chrome/common/extensions/url_pattern.h" |
| 17 #include "chrome/common/render_messages.h" | 17 #include "chrome/common/render_messages.h" |
| 18 #include "chrome/common/url_constants.h" | 18 #include "chrome/common/url_constants.h" |
| 19 #include "chrome/renderer/extensions/bindings_utils.h" | 19 #include "chrome/renderer/extensions/bindings_utils.h" |
| 20 #include "chrome/renderer/extensions/event_bindings.h" | 20 #include "chrome/renderer/extensions/event_bindings.h" |
| 21 #include "chrome/renderer/extensions/js_only_v8_extensions.h" | 21 #include "chrome/renderer/extensions/js_only_v8_extensions.h" |
| 22 #include "chrome/renderer/extensions/renderer_extension_bindings.h" | 22 #include "chrome/renderer/extensions/renderer_extension_bindings.h" |
| 23 #include "chrome/renderer/render_view.h" | 23 #include "chrome/renderer/render_view.h" |
| 24 #include "grit/common_resources.h" | 24 #include "grit/common_resources.h" |
| 25 #include "grit/renderer_resources.h" | 25 #include "grit/renderer_resources.h" |
| 26 #include "third_party/skia/include/core/SkBitmap.h" |
| 26 #include "webkit/api/public/WebFrame.h" | 27 #include "webkit/api/public/WebFrame.h" |
| 27 #include "webkit/api/public/WebURL.h" | 28 #include "webkit/api/public/WebURL.h" |
| 28 #include "webkit/api/public/WebKit.h" | 29 #include "webkit/api/public/WebKit.h" |
| 29 | 30 |
| 30 using bindings_utils::GetStringResource; | 31 using bindings_utils::GetStringResource; |
| 31 using bindings_utils::ContextInfo; | 32 using bindings_utils::ContextInfo; |
| 32 using bindings_utils::ContextList; | 33 using bindings_utils::ContextList; |
| 33 using bindings_utils::GetContexts; | 34 using bindings_utils::GetContexts; |
| 34 using bindings_utils::GetPendingRequestMap; | 35 using bindings_utils::GetPendingRequestMap; |
| 35 using bindings_utils::PendingRequest; | 36 using bindings_utils::PendingRequest; |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 133 } else if (name->Equals(v8::String::New("OpenChannelToTab"))) { | 134 } else if (name->Equals(v8::String::New("OpenChannelToTab"))) { |
| 134 return v8::FunctionTemplate::New(OpenChannelToTab); | 135 return v8::FunctionTemplate::New(OpenChannelToTab); |
| 135 } else if (name->Equals(v8::String::New("GetCurrentPageActions"))) { | 136 } else if (name->Equals(v8::String::New("GetCurrentPageActions"))) { |
| 136 return v8::FunctionTemplate::New(GetCurrentPageActions); | 137 return v8::FunctionTemplate::New(GetCurrentPageActions); |
| 137 } else if (name->Equals(v8::String::New("StartRequest"))) { | 138 } else if (name->Equals(v8::String::New("StartRequest"))) { |
| 138 return v8::FunctionTemplate::New(StartRequest); | 139 return v8::FunctionTemplate::New(StartRequest); |
| 139 } else if (name->Equals(v8::String::New("GetRenderViewId"))) { | 140 } else if (name->Equals(v8::String::New("GetRenderViewId"))) { |
| 140 return v8::FunctionTemplate::New(GetRenderViewId); | 141 return v8::FunctionTemplate::New(GetRenderViewId); |
| 141 } else if (name->Equals(v8::String::New("GetL10nMessage"))) { | 142 } else if (name->Equals(v8::String::New("GetL10nMessage"))) { |
| 142 return v8::FunctionTemplate::New(GetL10nMessage); | 143 return v8::FunctionTemplate::New(GetL10nMessage); |
| 144 } else if (name->Equals(v8::String::New("SetBrowserActionIcon"))) { |
| 145 return v8::FunctionTemplate::New(SetBrowserActionIcon); |
| 143 } | 146 } |
| 144 | 147 |
| 145 return ExtensionBase::GetNativeFunction(name); | 148 return ExtensionBase::GetNativeFunction(name); |
| 146 } | 149 } |
| 147 | 150 |
| 148 private: | 151 private: |
| 149 static v8::Handle<v8::Value> GetExtensionAPIDefinition( | 152 static v8::Handle<v8::Value> GetExtensionAPIDefinition( |
| 150 const v8::Arguments& args) { | 153 const v8::Arguments& args) { |
| 151 return v8::String::New(GetStringResource<IDR_EXTENSION_API_JSON>()); | 154 return v8::String::New(GetStringResource<IDR_EXTENSION_API_JSON>()); |
| 152 } | 155 } |
| (...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 323 } | 326 } |
| 324 } else { | 327 } else { |
| 325 NOTREACHED() << "Couldn't parse second parameter."; | 328 NOTREACHED() << "Couldn't parse second parameter."; |
| 326 return v8::Undefined(); | 329 return v8::Undefined(); |
| 327 } | 330 } |
| 328 | 331 |
| 329 return v8::String::New(UTF16ToUTF8(ReplaceStringPlaceholders( | 332 return v8::String::New(UTF16ToUTF8(ReplaceStringPlaceholders( |
| 330 UTF8ToUTF16(message), substitutions, NULL)).c_str()); | 333 UTF8ToUTF16(message), substitutions, NULL)).c_str()); |
| 331 } | 334 } |
| 332 | 335 |
| 333 // Starts an API request to the browser, with an optional callback. The | 336 // Common code for starting an API request to the browser. |value_args| |
| 334 // callback will be dispatched to EventBindings::HandleResponse. | 337 // contains the request's arguments. |
| 335 static v8::Handle<v8::Value> StartRequest(const v8::Arguments& args) { | 338 static v8::Handle<v8::Value> StartRequestCommon( |
| 339 const v8::Arguments& args, Value* value_args) { |
| 336 // Get the current RenderView so that we can send a routed IPC message from | 340 // Get the current RenderView so that we can send a routed IPC message from |
| 337 // the correct source. | 341 // the correct source. |
| 338 RenderView* renderview = bindings_utils::GetRenderViewForCurrentContext(); | 342 RenderView* renderview = bindings_utils::GetRenderViewForCurrentContext(); |
| 339 if (!renderview) | 343 if (!renderview) |
| 340 return v8::Undefined(); | 344 return v8::Undefined(); |
| 341 | 345 |
| 342 if (args.Length() != 4 || !args[0]->IsString() || !args[1]->IsString() || | |
| 343 !args[2]->IsInt32() || !args[3]->IsBoolean()) | |
| 344 return v8::Undefined(); | |
| 345 | |
| 346 std::string name = *v8::String::AsciiValue(args[0]); | 346 std::string name = *v8::String::AsciiValue(args[0]); |
| 347 if (GetFunctionNameSet()->find(name) == GetFunctionNameSet()->end()) { | 347 if (GetFunctionNameSet()->find(name) == GetFunctionNameSet()->end()) { |
| 348 NOTREACHED() << "Unexpected function " << name; | 348 NOTREACHED() << "Unexpected function " << name; |
| 349 return v8::Undefined(); | 349 return v8::Undefined(); |
| 350 } | 350 } |
| 351 | 351 |
| 352 if (!ExtensionProcessBindings::CurrentContextHasPermission(name)) { | 352 if (!ExtensionProcessBindings::CurrentContextHasPermission(name)) { |
| 353 return ExtensionProcessBindings::ThrowPermissionDeniedException(name); | 353 return ExtensionProcessBindings::ThrowPermissionDeniedException(name); |
| 354 } | 354 } |
| 355 | 355 |
| 356 std::string str_args = *v8::String::Utf8Value(args[1]); | |
| 357 int request_id = args[2]->Int32Value(); | 356 int request_id = args[2]->Int32Value(); |
| 358 bool has_callback = args[3]->BooleanValue(); | 357 bool has_callback = args[3]->BooleanValue(); |
| 359 | 358 |
| 360 ListValue args_holder; | |
| 361 JSONReader reader; | |
| 362 Value* json_args = reader.JsonToValue(str_args, false, false); | |
| 363 | |
| 364 // Since we do the serialization in the v8 extension, we should always get | |
| 365 // valid JSON. | |
| 366 if (!json_args) { | |
| 367 NOTREACHED() << "Invalid JSON passed to StartRequest."; | |
| 368 return v8::Undefined(); | |
| 369 } | |
| 370 | |
| 371 // Put the args in a 1-element list for easier serialization. Maybe all | 359 // Put the args in a 1-element list for easier serialization. Maybe all |
| 372 // requests should have a list of args? | 360 // requests should have a list of args? |
| 373 args_holder.Append(json_args); | 361 ListValue args_holder; |
| 362 args_holder.Append(value_args); |
| 374 | 363 |
| 375 v8::Persistent<v8::Context> current_context = | 364 v8::Persistent<v8::Context> current_context = |
| 376 v8::Persistent<v8::Context>::New(v8::Context::GetCurrent()); | 365 v8::Persistent<v8::Context>::New(v8::Context::GetCurrent()); |
| 377 DCHECK(!current_context.IsEmpty()); | 366 DCHECK(!current_context.IsEmpty()); |
| 378 GetPendingRequestMap()[request_id].reset(new PendingRequest( | 367 GetPendingRequestMap()[request_id].reset(new PendingRequest( |
| 379 current_context, name)); | 368 current_context, name)); |
| 380 | 369 |
| 381 renderview->SendExtensionRequest(name, args_holder, | 370 renderview->SendExtensionRequest(name, args_holder, |
| 382 request_id, has_callback); | 371 request_id, has_callback); |
| 383 | 372 |
| 384 return v8::Undefined(); | 373 return v8::Undefined(); |
| 385 } | 374 } |
| 386 | 375 |
| 376 // Starts an API request to the browser, with an optional callback. The |
| 377 // callback will be dispatched to EventBindings::HandleResponse. |
| 378 static v8::Handle<v8::Value> StartRequest(const v8::Arguments& args) { |
| 379 std::string str_args = *v8::String::Utf8Value(args[1]); |
| 380 JSONReader reader; |
| 381 Value* value_args = reader.JsonToValue(str_args, false, false); |
| 382 |
| 383 // Since we do the serialization in the v8 extension, we should always get |
| 384 // valid JSON. |
| 385 if (!value_args) { |
| 386 NOTREACHED() << "Invalid JSON passed to StartRequest."; |
| 387 return v8::Undefined(); |
| 388 } |
| 389 |
| 390 return StartRequestCommon(args, value_args); |
| 391 } |
| 392 |
| 393 // A special request for setting the browser action icon. This function |
| 394 // accepts a canvas ImageData object, so it needs to do extra processing |
| 395 // before sending the request to the browser. |
| 396 static v8::Handle<v8::Value> SetBrowserActionIcon(const v8::Arguments& args) { |
| 397 v8::Local<v8::Object> image_data = args[1]->ToObject(); |
| 398 v8::Local<v8::Object> data = |
| 399 image_data->Get(v8::String::New("data"))->ToObject(); |
| 400 int width = image_data->Get(v8::String::New("width"))->Int32Value(); |
| 401 int height = image_data->Get(v8::String::New("height"))->Int32Value(); |
| 402 |
| 403 int data_length = data->Get(v8::String::New("length"))->Int32Value(); |
| 404 if (data_length != 4 * width * height) { |
| 405 NOTREACHED() << |
| 406 "Invalid argument to browserAction.setIcon. Expecting ImageData."; |
| 407 return v8::Undefined(); |
| 408 } |
| 409 |
| 410 SkBitmap bitmap; |
| 411 bitmap.setConfig(SkBitmap::kARGB_8888_Config, width, height); |
| 412 bitmap.allocPixels(); |
| 413 bitmap.eraseARGB(0, 0, 0, 0); |
| 414 |
| 415 uint32_t* pixels = bitmap.getAddr32(0, 0); |
| 416 for (int t = 0; t < width*height; t++) { |
| 417 // |data| is RGBA, pixels is ARGB. |
| 418 pixels[t] = |
| 419 ((data->Get(v8::Integer::New(4*t + 3))->Int32Value() & 0xFF) << 24) | |
| 420 ((data->Get(v8::Integer::New(4*t + 0))->Int32Value() & 0xFF) << 16) | |
| 421 ((data->Get(v8::Integer::New(4*t + 1))->Int32Value() & 0xFF) << 8) | |
| 422 ((data->Get(v8::Integer::New(4*t + 2))->Int32Value() & 0xFF) << 0); |
| 423 } |
| 424 |
| 425 // Construct the Value object. |
| 426 IPC::Message bitmap_pickle; |
| 427 IPC::WriteParam(&bitmap_pickle, bitmap); |
| 428 Value* bitmap_value = BinaryValue::CreateWithCopiedBuffer( |
| 429 static_cast<const char*>(bitmap_pickle.data()), bitmap_pickle.size()); |
| 430 |
| 431 return StartRequestCommon(args, bitmap_value); |
| 432 } |
| 433 |
| 387 static v8::Handle<v8::Value> GetRenderViewId(const v8::Arguments& args) { | 434 static v8::Handle<v8::Value> GetRenderViewId(const v8::Arguments& args) { |
| 388 RenderView* renderview = bindings_utils::GetRenderViewForCurrentContext(); | 435 RenderView* renderview = bindings_utils::GetRenderViewForCurrentContext(); |
| 389 if (!renderview) | 436 if (!renderview) |
| 390 return v8::Undefined(); | 437 return v8::Undefined(); |
| 391 return v8::Integer::New(renderview->routing_id()); | 438 return v8::Integer::New(renderview->routing_id()); |
| 392 } | 439 } |
| 393 }; | 440 }; |
| 394 | 441 |
| 395 } // namespace | 442 } // namespace |
| 396 | 443 |
| (...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 533 return; | 580 return; |
| 534 | 581 |
| 535 v8::HandleScope handle_scope; | 582 v8::HandleScope handle_scope; |
| 536 WebFrame* frame = view->mainFrame(); | 583 WebFrame* frame = view->mainFrame(); |
| 537 v8::Local<v8::Context> context = frame->mainWorldScriptContext(); | 584 v8::Local<v8::Context> context = frame->mainWorldScriptContext(); |
| 538 v8::Handle<v8::Value> argv[1]; | 585 v8::Handle<v8::Value> argv[1]; |
| 539 argv[0] = v8::String::New(type_str); | 586 argv[0] = v8::String::New(type_str); |
| 540 bindings_utils::CallFunctionInContext(context, "setViewType", | 587 bindings_utils::CallFunctionInContext(context, "setViewType", |
| 541 arraysize(argv), argv); | 588 arraysize(argv), argv); |
| 542 } | 589 } |
| OLD | NEW |