1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "extensions/browser/api/declarative/declarative_api.h" 6 7 #include "base/base64.h" 8 #include "base/bind.h" 9 #include "base/bind_helpers.h" 10 #include "base/task_runner_util.h" 11 #include "base/values.h" 12 #include "content/public/browser/browser_thread.h" 13 #include "content/public/browser/render_process_host.h" 14 #include "content/public/browser/render_view_host.h" 15 #include "content/public/browser/web_contents.h" 16 #include "extensions/browser/api/extensions_api_client.h" 17 #include "extensions/browser/extension_system.h" 18 #include "extensions/browser/guest_view/web_view/web_view_constants.h" 19 #include "extensions/browser/guest_view/web_view/web_view_guest.h" 20 #include "extensions/common/api/events.h" 21 #include "extensions/common/extension_api.h" 22 #include "extensions/common/permissions/permissions_data.h" 23 24 using extensions::core_api::events::Rule; 25 26 namespace AddRules = extensions::core_api::events::Event::AddRules; 27 namespace GetRules = extensions::core_api::events::Event::GetRules; 28 namespace RemoveRules = extensions::core_api::events::Event::RemoveRules; 29 30 31 namespace extensions { 32 33 namespace { 34 35 const char kWebRequest[] = "declarativeWebRequest."; 36 const char kWebViewExpectedError[] = "Webview event with Webview ID expected."; 37 38 bool IsWebViewEvent(const std::string& event_name) { 39 // Sample event names: 40 // webViewInternal.onRequest. 41 // webViewInternal.onMessage. 42 return event_name.compare(0, 43 strlen(webview::kWebViewEventPrefix), 44 webview::kWebViewEventPrefix) == 0; 45 } 46 47 std::string GetWebRequestEventName(const std::string& event_name) { 48 std::string web_request_event_name(event_name); 49 if (IsWebViewEvent(web_request_event_name)) { 50 web_request_event_name.replace( 51 0, strlen(webview::kWebViewEventPrefix), kWebRequest); 52 } 53 return web_request_event_name; 54 } 55 56 void ConvertBinaryDictionaryValuesToBase64(base::DictionaryValue* dict); 57 58 // Encodes |binary| as base64 and returns a new StringValue populated with the 59 // encoded string. 60 scoped_ptr<base::StringValue> ConvertBinaryToBase64(base::BinaryValue* binary) { 61 std::string binary_data = std::string(binary->GetBuffer(), binary->GetSize()); 62 std::string data64; 63 base::Base64Encode(binary_data, &data64); 64 return scoped_ptr<base::StringValue>(new base::StringValue(data64)); 65 } 66 67 // Parses through |args| replacing any BinaryValues with base64 encoded 68 // StringValues. Recurses over any nested ListValues, and calls 69 // ConvertBinaryDictionaryValuesToBase64 for any nested DictionaryValues. 70 void ConvertBinaryListElementsToBase64(base::ListValue* args) { 71 size_t index = 0; 72 for (base::ListValue::iterator iter = args->begin(); iter != args->end(); 73 ++iter, ++index) { 74 if ((*iter)->IsType(base::Value::TYPE_BINARY)) { 75 base::BinaryValue* binary = NULL; 76 if (args->GetBinary(index, &binary)) 77 args->Set(index, ConvertBinaryToBase64(binary).release()); 78 } else if ((*iter)->IsType(base::Value::TYPE_LIST)) { 79 base::ListValue* list; 80 (*iter)->GetAsList(&list); 81 ConvertBinaryListElementsToBase64(list); 82 } else if ((*iter)->IsType(base::Value::TYPE_DICTIONARY)) { 83 base::DictionaryValue* dict; 84 (*iter)->GetAsDictionary(&dict); 85 ConvertBinaryDictionaryValuesToBase64(dict); 86 } 87 } 88 } 89 90 // Parses through |dict| replacing any BinaryValues with base64 encoded 91 // StringValues. Recurses over any nested DictionaryValues, and calls 92 // ConvertBinaryListElementsToBase64 for any nested ListValues. 93 void ConvertBinaryDictionaryValuesToBase64(base::DictionaryValue* dict) { 94 for (base::DictionaryValue::Iterator iter(*dict); !iter.IsAtEnd(); 95 iter.Advance()) { 96 if (iter.value().IsType(base::Value::TYPE_BINARY)) { 97 base::BinaryValue* binary = NULL; 98 if (dict->GetBinary(iter.key(), &binary)) 99 dict->Set(iter.key(), ConvertBinaryToBase64(binary).release()); 100 } else if (iter.value().IsType(base::Value::TYPE_LIST)) { 101 const base::ListValue* list; 102 iter.value().GetAsList(&list); 103 ConvertBinaryListElementsToBase64(const_cast<base::ListValue*>(list)); 104 } else if (iter.value().IsType(base::Value::TYPE_DICTIONARY)) { 105 const base::DictionaryValue* dict; 106 iter.value().GetAsDictionary(&dict); 107 ConvertBinaryDictionaryValuesToBase64( 108 const_cast<base::DictionaryValue*>(dict)); 109 } 110 } 111 } 112 113 } // namespace 114 115 RulesFunction::RulesFunction() 116 : rules_registry_(NULL) { 117 } 118 119 RulesFunction::~RulesFunction() {} 120 121 bool RulesFunction::HasPermission() { 122 std::string event_name; 123 EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &event_name)); 124 if (IsWebViewEvent(event_name) && 125 extension_->permissions_data()->HasAPIPermission( 126 extensions::APIPermission::kWebView)) 127 return true; 128 Feature::Availability availability = 129 ExtensionAPI::GetSharedInstance()->IsAvailable( 130 event_name, 131 extension_.get(), 132 Feature::BLESSED_EXTENSION_CONTEXT, 133 source_url()); 134 return availability.is_available(); 135 } 136 137 bool RulesFunction::RunAsync() { 138 std::string event_name; 139 EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &event_name)); 140 141 int webview_instance_id = 0; 142 EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(1, &webview_instance_id)); 143 int embedder_process_id = render_view_host()->GetProcess()->GetID(); 144 145 bool has_webview = webview_instance_id != 0; 146 if (has_webview != IsWebViewEvent(event_name)) 147 EXTENSION_FUNCTION_ERROR(kWebViewExpectedError); 148 event_name = GetWebRequestEventName(event_name); 149 150 // If we are not operating on a particular <webview>, then the key is (0, 0). 151 RulesRegistry::WebViewKey key( 152 webview_instance_id ? embedder_process_id : 0, webview_instance_id); 153 154 // The following call will return a NULL pointer for apps_shell, but should 155 // never be called there anyways. 156 rules_registry_ = ExtensionsAPIClient::Get()->GetRulesRegistry( 157 browser_context(), key, event_name); 158 DCHECK(rules_registry_.get()); 159 // Raw access to this function is not available to extensions, therefore 160 // there should never be a request for a nonexisting rules registry. 161 EXTENSION_FUNCTION_VALIDATE(rules_registry_.get()); 162 163 if (content::BrowserThread::CurrentlyOn(rules_registry_->owner_thread())) { 164 bool success = RunAsyncOnCorrectThread(); 165 SendResponse(success); 166 } else { 167 scoped_refptr<base::MessageLoopProxy> message_loop_proxy = 168 content::BrowserThread::GetMessageLoopProxyForThread( 169 rules_registry_->owner_thread()); 170 base::PostTaskAndReplyWithResult( 171 message_loop_proxy.get(), 172 FROM_HERE, 173 base::Bind(&RulesFunction::RunAsyncOnCorrectThread, this), 174 base::Bind(&RulesFunction::SendResponse, this)); 175 } 176 177 return true; 178 } 179 180 bool EventsEventAddRulesFunction::RunAsyncOnCorrectThread() { 181 ConvertBinaryListElementsToBase64(args_.get()); 182 scoped_ptr<AddRules::Params> params(AddRules::Params::Create(*args_)); 183 EXTENSION_FUNCTION_VALIDATE(params.get()); 184 185 error_ = rules_registry_->AddRules(extension_id(), params->rules); 186 187 if (error_.empty()) 188 results_ = AddRules::Results::Create(params->rules); 189 190 return error_.empty(); 191 } 192 193 bool EventsEventRemoveRulesFunction::RunAsyncOnCorrectThread() { 194 scoped_ptr<RemoveRules::Params> params(RemoveRules::Params::Create(*args_)); 195 EXTENSION_FUNCTION_VALIDATE(params.get()); 196 197 if (params->rule_identifiers.get()) { 198 error_ = rules_registry_->RemoveRules(extension_id(), 199 *params->rule_identifiers); 200 } else { 201 error_ = rules_registry_->RemoveAllRules(extension_id()); 202 } 203 204 return error_.empty(); 205 } 206 207 bool EventsEventGetRulesFunction::RunAsyncOnCorrectThread() { 208 scoped_ptr<GetRules::Params> params(GetRules::Params::Create(*args_)); 209 EXTENSION_FUNCTION_VALIDATE(params.get()); 210 211 std::vector<linked_ptr<Rule> > rules; 212 if (params->rule_identifiers.get()) { 213 rules_registry_->GetRules( 214 extension_id(), *params->rule_identifiers, &rules); 215 } else { 216 rules_registry_->GetAllRules(extension_id(), &rules); 217 } 218 219 results_ = GetRules::Results::Create(rules); 220 221 return true; 222 } 223 224 } // namespace extensions 225