| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 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 "chrome/browser/extensions/extension_tabs_module.h" | 5 #include "chrome/browser/extensions/extension_tabs_module.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <vector> | 8 #include <vector> |
| 9 | 9 |
| 10 #include "base/base64.h" | 10 #include "base/base64.h" |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 60 #include "ui/gfx/codec/png_codec.h" | 60 #include "ui/gfx/codec/png_codec.h" |
| 61 | 61 |
| 62 namespace keys = extension_tabs_module_constants; | 62 namespace keys = extension_tabs_module_constants; |
| 63 namespace errors = extension_manifest_errors; | 63 namespace errors = extension_manifest_errors; |
| 64 | 64 |
| 65 using content::NavigationController; | 65 using content::NavigationController; |
| 66 using content::NavigationEntry; | 66 using content::NavigationEntry; |
| 67 using content::OpenURLParams; | 67 using content::OpenURLParams; |
| 68 using content::Referrer; | 68 using content::Referrer; |
| 69 using content::WebContents; | 69 using content::WebContents; |
| 70 using extensions::tabs_module::IsCrashURL; |
| 71 using extensions::tabs_module::ResolvePossiblyRelativeURL; |
| 70 | 72 |
| 71 const int CaptureVisibleTabFunction::kDefaultQuality = 90; | 73 const int CaptureVisibleTabFunction::kDefaultQuality = 90; |
| 72 | 74 |
| 73 namespace { | 75 namespace { |
| 74 | 76 |
| 75 // |error_message| can optionally be passed in a will be set with an appropriate | 77 // |error_message| can optionally be passed in a will be set with an appropriate |
| 76 // message if the window cannot be found by id. | 78 // message if the window cannot be found by id. |
| 77 Browser* GetBrowserInProfileWithId(Profile* profile, | 79 Browser* GetBrowserInProfileWithId(Profile* profile, |
| 78 const int window_id, | 80 const int window_id, |
| 79 bool include_incognito, | 81 bool include_incognito, |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 131 browser, tab_strip, contents, tab_index)) | 133 browser, tab_strip, contents, tab_index)) |
| 132 return true; | 134 return true; |
| 133 | 135 |
| 134 if (error_message) | 136 if (error_message) |
| 135 *error_message = ExtensionErrorUtils::FormatErrorMessage( | 137 *error_message = ExtensionErrorUtils::FormatErrorMessage( |
| 136 keys::kTabNotFoundError, base::IntToString(tab_id)); | 138 keys::kTabNotFoundError, base::IntToString(tab_id)); |
| 137 | 139 |
| 138 return false; | 140 return false; |
| 139 } | 141 } |
| 140 | 142 |
| 141 // Takes |url_string| and returns a GURL which is either valid and absolute | |
| 142 // or invalid. If |url_string| is not directly interpretable as a valid (it is | |
| 143 // likely a relative URL) an attempt is made to resolve it. |extension| is | |
| 144 // provided so it can be resolved relative to its extension base | |
| 145 // (chrome-extension://<id>/). Using the source frame url would be more correct, | |
| 146 // but because the api shipped with urls resolved relative to their extension | |
| 147 // base, we decided it wasn't worth breaking existing extensions to fix. | |
| 148 GURL ResolvePossiblyRelativeURL(const std::string& url_string, | |
| 149 const Extension* extension) { | |
| 150 GURL url = GURL(url_string); | |
| 151 if (!url.is_valid()) | |
| 152 url = extension->GetResourceURL(url_string); | |
| 153 | |
| 154 return url; | |
| 155 } | |
| 156 | |
| 157 bool IsCrashURL(const GURL& url) { | |
| 158 // Check a fixed-up URL, to normalize the scheme and parse hosts correctly. | |
| 159 GURL fixed_url = | |
| 160 URLFixerUpper::FixupURL(url.possibly_invalid_spec(), std::string()); | |
| 161 return (fixed_url.SchemeIs(chrome::kChromeUIScheme) && | |
| 162 (fixed_url.host() == chrome::kChromeUIBrowserCrashHost || | |
| 163 fixed_url.host() == chrome::kChromeUICrashHost)); | |
| 164 } | |
| 165 | |
| 166 // Reads the |value| as either a single integer value or a list of integers. | 143 // Reads the |value| as either a single integer value or a list of integers. |
| 167 bool ReadOneOrMoreIntegers( | 144 bool ReadOneOrMoreIntegers( |
| 168 Value* value, std::vector<int>* result) { | 145 Value* value, std::vector<int>* result) { |
| 169 if (value->IsType(Value::TYPE_INTEGER)) { | 146 if (value->IsType(Value::TYPE_INTEGER)) { |
| 170 int tab_id = -1; | 147 int tab_id = -1; |
| 171 if (!value->GetAsInteger(&tab_id)) | 148 if (!value->GetAsInteger(&tab_id)) |
| 172 return false; | 149 return false; |
| 173 result->push_back(tab_id); | 150 result->push_back(tab_id); |
| 174 return true; | 151 return true; |
| 175 | 152 |
| (...skipping 29 matching lines...) Expand all Loading... |
| 205 if (query->HasKey(key)) { | 182 if (query->HasKey(key)) { |
| 206 bool value = false; | 183 bool value = false; |
| 207 CHECK(query->GetBoolean(key, &value)); | 184 CHECK(query->GetBoolean(key, &value)); |
| 208 return value ? MATCH_TRUE : MATCH_FALSE; | 185 return value ? MATCH_TRUE : MATCH_FALSE; |
| 209 } | 186 } |
| 210 return NOT_SET; | 187 return NOT_SET; |
| 211 } | 188 } |
| 212 | 189 |
| 213 } // namespace | 190 } // namespace |
| 214 | 191 |
| 192 namespace extensions { |
| 193 namespace tabs_module { |
| 194 |
| 195 GURL ResolvePossiblyRelativeURL(const std::string& url_string, |
| 196 const Extension* extension) { |
| 197 GURL url = GURL(url_string); |
| 198 if (!url.is_valid()) |
| 199 url = extension->GetResourceURL(url_string); |
| 200 |
| 201 return url; |
| 202 } |
| 203 |
| 204 bool IsCrashURL(const GURL& url) { |
| 205 // Check a fixed-up URL, to normalize the scheme and parse hosts correctly. |
| 206 GURL fixed_url = |
| 207 URLFixerUpper::FixupURL(url.possibly_invalid_spec(), std::string()); |
| 208 return (fixed_url.SchemeIs(chrome::kChromeUIScheme) && |
| 209 (fixed_url.host() == chrome::kChromeUIBrowserCrashHost || |
| 210 fixed_url.host() == chrome::kChromeUICrashHost)); |
| 211 } |
| 212 |
| 213 } // namespace tabs_module |
| 214 } // namespace extensions |
| 215 |
| 215 // Windows --------------------------------------------------------------------- | 216 // Windows --------------------------------------------------------------------- |
| 216 | 217 |
| 217 bool GetWindowFunction::RunImpl() { | 218 bool GetWindowFunction::RunImpl() { |
| 218 int window_id = extension_misc::kUnknownWindowId; | 219 int window_id = extension_misc::kUnknownWindowId; |
| 219 EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &window_id)); | 220 EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &window_id)); |
| 220 | 221 |
| 221 bool populate_tabs = false; | 222 bool populate_tabs = false; |
| 222 if (HasOptionalArgument(1)) { | 223 if (HasOptionalArgument(1)) { |
| 223 DictionaryValue* args = NULL; | 224 DictionaryValue* args = NULL; |
| 224 EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(1, &args)); | 225 EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(1, &args)); |
| (...skipping 835 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1060 } else { | 1061 } else { |
| 1061 EXTENSION_FUNCTION_VALIDATE(tab_value->GetAsInteger(&tab_id)); | 1062 EXTENSION_FUNCTION_VALIDATE(tab_value->GetAsInteger(&tab_id)); |
| 1062 } | 1063 } |
| 1063 | 1064 |
| 1064 int tab_index = -1; | 1065 int tab_index = -1; |
| 1065 TabStripModel* tab_strip = NULL; | 1066 TabStripModel* tab_strip = NULL; |
| 1066 if (!GetTabById(tab_id, profile(), include_incognito(), | 1067 if (!GetTabById(tab_id, profile(), include_incognito(), |
| 1067 NULL, &tab_strip, &contents, &tab_index, &error_)) { | 1068 NULL, &tab_strip, &contents, &tab_index, &error_)) { |
| 1068 return false; | 1069 return false; |
| 1069 } | 1070 } |
| 1070 NavigationController& controller = contents->web_contents()->GetController(); | |
| 1071 | 1071 |
| 1072 // TODO(rafaelw): handle setting remaining tab properties: | 1072 // TODO(rafaelw): handle setting remaining tab properties: |
| 1073 // -title | 1073 // -title |
| 1074 // -favIconUrl | 1074 // -favIconUrl |
| 1075 | 1075 |
| 1076 // Navigate the tab to a new location if the url is different. | 1076 // Navigate the tab to a new location if the url is different. |
| 1077 std::string url_string; | 1077 bool is_async = false; |
| 1078 if (update_props->HasKey(keys::kUrlKey)) { | 1078 if (!UpdateURLIfPresent(update_props, contents->web_contents(), &is_async)) |
| 1079 EXTENSION_FUNCTION_VALIDATE(update_props->GetString( | 1079 return false; |
| 1080 keys::kUrlKey, &url_string)); | |
| 1081 GURL url = ResolvePossiblyRelativeURL(url_string, GetExtension()); | |
| 1082 | |
| 1083 if (!url.is_valid()) { | |
| 1084 error_ = ExtensionErrorUtils::FormatErrorMessage(keys::kInvalidUrlError, | |
| 1085 url_string); | |
| 1086 return false; | |
| 1087 } | |
| 1088 | |
| 1089 // Don't let the extension crash the browser or renderers. | |
| 1090 if (IsCrashURL(url)) { | |
| 1091 error_ = keys::kNoCrashBrowserError; | |
| 1092 return false; | |
| 1093 } | |
| 1094 | |
| 1095 // JavaScript URLs can do the same kinds of things as cross-origin XHR, so | |
| 1096 // we need to check host permissions before allowing them. | |
| 1097 if (url.SchemeIs(chrome::kJavaScriptScheme)) { | |
| 1098 if (!GetExtension()->CanExecuteScriptOnPage( | |
| 1099 contents->web_contents()->GetURL(), NULL, &error_)) { | |
| 1100 return false; | |
| 1101 } | |
| 1102 | |
| 1103 ExtensionMsg_ExecuteCode_Params params; | |
| 1104 params.request_id = request_id(); | |
| 1105 params.extension_id = extension_id(); | |
| 1106 params.is_javascript = true; | |
| 1107 params.code = url.path(); | |
| 1108 params.all_frames = false; | |
| 1109 params.in_main_world = true; | |
| 1110 | |
| 1111 RenderViewHost* render_view_host = | |
| 1112 contents->web_contents()->GetRenderViewHost(); | |
| 1113 render_view_host->Send( | |
| 1114 new ExtensionMsg_ExecuteCode(render_view_host->routing_id(), | |
| 1115 params)); | |
| 1116 | |
| 1117 Observe(contents->web_contents()); | |
| 1118 AddRef(); // balanced in Observe() | |
| 1119 | |
| 1120 return true; | |
| 1121 } | |
| 1122 | |
| 1123 controller.LoadURL( | |
| 1124 url, content::Referrer(), content::PAGE_TRANSITION_LINK, std::string()); | |
| 1125 | |
| 1126 // The URL of a tab contents never actually changes to a JavaScript URL, so | |
| 1127 // this check only makes sense in other cases. | |
| 1128 if (!url.SchemeIs(chrome::kJavaScriptScheme)) | |
| 1129 DCHECK_EQ(url.spec(), contents->web_contents()->GetURL().spec()); | |
| 1130 } | |
| 1131 | 1080 |
| 1132 bool active = false; | 1081 bool active = false; |
| 1133 // TODO(rafaelw): Setting |active| from js doesn't make much sense. | 1082 // TODO(rafaelw): Setting |active| from js doesn't make much sense. |
| 1134 // Move tab selection management up to window. | 1083 // Move tab selection management up to window. |
| 1135 if (update_props->HasKey(keys::kSelectedKey)) | 1084 if (update_props->HasKey(keys::kSelectedKey)) |
| 1136 EXTENSION_FUNCTION_VALIDATE(update_props->GetBoolean( | 1085 EXTENSION_FUNCTION_VALIDATE(update_props->GetBoolean( |
| 1137 keys::kSelectedKey, &active)); | 1086 keys::kSelectedKey, &active)); |
| 1138 | 1087 |
| 1139 // The 'active' property has replaced 'selected'. | 1088 // The 'active' property has replaced 'selected'. |
| 1140 if (update_props->HasKey(keys::kActiveKey)) | 1089 if (update_props->HasKey(keys::kActiveKey)) |
| (...skipping 29 matching lines...) Expand all Loading... |
| 1170 if (has_callback()) { | 1119 if (has_callback()) { |
| 1171 if (GetExtension()->HasAPIPermission(ExtensionAPIPermission::kTab)) { | 1120 if (GetExtension()->HasAPIPermission(ExtensionAPIPermission::kTab)) { |
| 1172 result_.reset(ExtensionTabUtil::CreateTabValue(contents->web_contents(), | 1121 result_.reset(ExtensionTabUtil::CreateTabValue(contents->web_contents(), |
| 1173 tab_strip, | 1122 tab_strip, |
| 1174 tab_index)); | 1123 tab_index)); |
| 1175 } else { | 1124 } else { |
| 1176 result_.reset(Value::CreateNullValue()); | 1125 result_.reset(Value::CreateNullValue()); |
| 1177 } | 1126 } |
| 1178 } | 1127 } |
| 1179 | 1128 |
| 1180 SendResponse(true); | 1129 if (!is_async) |
| 1130 SendResponse(true); |
| 1131 |
| 1181 return true; | 1132 return true; |
| 1182 } | 1133 } |
| 1183 | 1134 |
| 1135 bool UpdateTabFunction::UpdateURLIfPresent(DictionaryValue* update_props, |
| 1136 WebContents* web_contents, |
| 1137 bool* is_async) { |
| 1138 if (!update_props->HasKey(keys::kUrlKey)) |
| 1139 return true; |
| 1140 |
| 1141 std::string url_string; |
| 1142 EXTENSION_FUNCTION_VALIDATE(update_props->GetString( |
| 1143 keys::kUrlKey, &url_string)); |
| 1144 GURL url = ResolvePossiblyRelativeURL(url_string, GetExtension()); |
| 1145 |
| 1146 if (!url.is_valid()) { |
| 1147 error_ = ExtensionErrorUtils::FormatErrorMessage( |
| 1148 keys::kInvalidUrlError, url_string); |
| 1149 return false; |
| 1150 } |
| 1151 |
| 1152 // Don't let the extension crash the browser or renderers. |
| 1153 if (IsCrashURL(url)) { |
| 1154 error_ = keys::kNoCrashBrowserError; |
| 1155 return false; |
| 1156 } |
| 1157 |
| 1158 // JavaScript URLs can do the same kinds of things as cross-origin XHR, so |
| 1159 // we need to check host permissions before allowing them. |
| 1160 if (url.SchemeIs(chrome::kJavaScriptScheme)) { |
| 1161 if (!GetExtension()->CanExecuteScriptOnPage( |
| 1162 web_contents->GetURL(), NULL, &error_)) { |
| 1163 return false; |
| 1164 } |
| 1165 |
| 1166 ExtensionMsg_ExecuteCode_Params params; |
| 1167 params.request_id = request_id(); |
| 1168 params.extension_id = extension_id(); |
| 1169 params.is_javascript = true; |
| 1170 params.code = url.path(); |
| 1171 params.all_frames = false; |
| 1172 params.in_main_world = true; |
| 1173 |
| 1174 RenderViewHost* render_view_host = web_contents->GetRenderViewHost(); |
| 1175 render_view_host->Send( |
| 1176 new ExtensionMsg_ExecuteCode(render_view_host->routing_id(), params)); |
| 1177 |
| 1178 Observe(web_contents); |
| 1179 AddRef(); // Balanced in OnExecuteCodeFinished(). |
| 1180 |
| 1181 // Tell the caller to wait for the response. |
| 1182 *is_async = true; |
| 1183 return true; |
| 1184 } |
| 1185 |
| 1186 web_contents->GetController().LoadURL( |
| 1187 url, content::Referrer(), content::PAGE_TRANSITION_LINK, std::string()); |
| 1188 |
| 1189 // The URL of a tab contents never actually changes to a JavaScript URL, so |
| 1190 // this check only makes sense in other cases. |
| 1191 if (!url.SchemeIs(chrome::kJavaScriptScheme)) |
| 1192 DCHECK_EQ(url.spec(), web_contents->GetURL().spec()); |
| 1193 |
| 1194 return true; |
| 1195 } |
| 1196 |
| 1184 bool UpdateTabFunction::OnMessageReceived(const IPC::Message& message) { | 1197 bool UpdateTabFunction::OnMessageReceived(const IPC::Message& message) { |
| 1185 if (message.type() != ExtensionHostMsg_ExecuteCodeFinished::ID) | 1198 if (message.type() != ExtensionHostMsg_ExecuteCodeFinished::ID) |
| 1186 return false; | 1199 return false; |
| 1187 | 1200 |
| 1188 int message_request_id = -1; | 1201 int message_request_id = -1; |
| 1189 void* iter = NULL; | 1202 void* iter = NULL; |
| 1190 if (!message.ReadInt(&iter, &message_request_id)) { | 1203 if (!message.ReadInt(&iter, &message_request_id)) { |
| 1191 NOTREACHED() << "malformed extension message"; | 1204 NOTREACHED() << "malformed extension message"; |
| 1192 return true; | 1205 return true; |
| 1193 } | 1206 } |
| (...skipping 12 matching lines...) Expand all Loading... |
| 1206 bool success, | 1219 bool success, |
| 1207 const std::string& error) { | 1220 const std::string& error) { |
| 1208 if (!error.empty()) { | 1221 if (!error.empty()) { |
| 1209 CHECK(!success); | 1222 CHECK(!success); |
| 1210 error_ = error; | 1223 error_ = error; |
| 1211 } | 1224 } |
| 1212 | 1225 |
| 1213 SendResponse(success); | 1226 SendResponse(success); |
| 1214 | 1227 |
| 1215 Observe(NULL); | 1228 Observe(NULL); |
| 1216 Release(); // balanced in Execute() | 1229 Release(); // Balanced in UpdateURLIfPresent(). |
| 1217 } | 1230 } |
| 1218 | 1231 |
| 1219 bool MoveTabsFunction::RunImpl() { | 1232 bool MoveTabsFunction::RunImpl() { |
| 1220 Value* tab_value = NULL; | 1233 Value* tab_value = NULL; |
| 1221 EXTENSION_FUNCTION_VALIDATE(args_->Get(0, &tab_value)); | 1234 EXTENSION_FUNCTION_VALIDATE(args_->Get(0, &tab_value)); |
| 1222 | 1235 |
| 1223 std::vector<int> tab_ids; | 1236 std::vector<int> tab_ids; |
| 1224 EXTENSION_FUNCTION_VALIDATE(ReadOneOrMoreIntegers(tab_value, &tab_ids)); | 1237 EXTENSION_FUNCTION_VALIDATE(ReadOneOrMoreIntegers(tab_value, &tab_ids)); |
| 1225 | 1238 |
| 1226 DictionaryValue* update_props = NULL; | 1239 DictionaryValue* update_props = NULL; |
| (...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1409 // is being dragged, or we're in some other nested event loop. This code | 1422 // is being dragged, or we're in some other nested event loop. This code |
| 1410 // path should ensure that the tab is safely closed under such | 1423 // path should ensure that the tab is safely closed under such |
| 1411 // circumstances, whereas |Browser::CloseTabContents()| does not. | 1424 // circumstances, whereas |Browser::CloseTabContents()| does not. |
| 1412 RenderViewHost* render_view_host = | 1425 RenderViewHost* render_view_host = |
| 1413 contents->web_contents()->GetRenderViewHost(); | 1426 contents->web_contents()->GetRenderViewHost(); |
| 1414 render_view_host->delegate()->Close(render_view_host); | 1427 render_view_host->delegate()->Close(render_view_host); |
| 1415 } | 1428 } |
| 1416 return true; | 1429 return true; |
| 1417 } | 1430 } |
| 1418 | 1431 |
| 1419 bool CaptureVisibleTabFunction::RunImpl() { | 1432 bool CaptureVisibleTabFunction::GetTabToCapture( |
| 1433 WebContents** web_contents, TabContentsWrapper** wrapper) { |
| 1420 Browser* browser = NULL; | 1434 Browser* browser = NULL; |
| 1421 // windowId defaults to "current" window. | 1435 // windowId defaults to "current" window. |
| 1422 int window_id = extension_misc::kCurrentWindowId; | 1436 int window_id = extension_misc::kCurrentWindowId; |
| 1423 | 1437 |
| 1424 if (HasOptionalArgument(0)) | 1438 if (HasOptionalArgument(0)) |
| 1425 EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &window_id)); | 1439 EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &window_id)); |
| 1426 | 1440 |
| 1427 if (!GetBrowserFromWindowID(this, window_id, &browser)) | 1441 if (!GetBrowserFromWindowID(this, window_id, &browser)) |
| 1428 return false; | 1442 return false; |
| 1429 | 1443 |
| 1444 *web_contents = browser->GetSelectedWebContents(); |
| 1445 if (*web_contents == NULL) { |
| 1446 error_ = keys::kInternalVisibleTabCaptureError; |
| 1447 return false; |
| 1448 } |
| 1449 |
| 1450 *wrapper = browser->GetSelectedTabContentsWrapper(); |
| 1451 |
| 1452 return true; |
| 1453 }; |
| 1454 |
| 1455 bool CaptureVisibleTabFunction::RunImpl() { |
| 1456 WebContents* web_contents = NULL; |
| 1457 TabContentsWrapper* wrapper = NULL; |
| 1458 if (!GetTabToCapture(&web_contents, &wrapper)) |
| 1459 return false; |
| 1460 |
| 1430 image_format_ = FORMAT_JPEG; // Default format is JPEG. | 1461 image_format_ = FORMAT_JPEG; // Default format is JPEG. |
| 1431 image_quality_ = kDefaultQuality; // Default quality setting. | 1462 image_quality_ = kDefaultQuality; // Default quality setting. |
| 1432 | 1463 |
| 1433 if (HasOptionalArgument(1)) { | 1464 if (HasOptionalArgument(1)) { |
| 1434 DictionaryValue* options = NULL; | 1465 DictionaryValue* options = NULL; |
| 1435 EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(1, &options)); | 1466 EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(1, &options)); |
| 1436 | 1467 |
| 1437 if (options->HasKey(keys::kFormatKey)) { | 1468 if (options->HasKey(keys::kFormatKey)) { |
| 1438 std::string format; | 1469 std::string format; |
| 1439 EXTENSION_FUNCTION_VALIDATE( | 1470 EXTENSION_FUNCTION_VALIDATE( |
| 1440 options->GetString(keys::kFormatKey, &format)); | 1471 options->GetString(keys::kFormatKey, &format)); |
| 1441 | 1472 |
| 1442 if (format == keys::kFormatValueJpeg) { | 1473 if (format == keys::kFormatValueJpeg) { |
| 1443 image_format_ = FORMAT_JPEG; | 1474 image_format_ = FORMAT_JPEG; |
| 1444 } else if (format == keys::kFormatValuePng) { | 1475 } else if (format == keys::kFormatValuePng) { |
| 1445 image_format_ = FORMAT_PNG; | 1476 image_format_ = FORMAT_PNG; |
| 1446 } else { | 1477 } else { |
| 1447 // Schema validation should make this unreachable. | 1478 // Schema validation should make this unreachable. |
| 1448 EXTENSION_FUNCTION_VALIDATE(0); | 1479 EXTENSION_FUNCTION_VALIDATE(0); |
| 1449 } | 1480 } |
| 1450 } | 1481 } |
| 1451 | 1482 |
| 1452 if (options->HasKey(keys::kQualityKey)) { | 1483 if (options->HasKey(keys::kQualityKey)) { |
| 1453 EXTENSION_FUNCTION_VALIDATE( | 1484 EXTENSION_FUNCTION_VALIDATE( |
| 1454 options->GetInteger(keys::kQualityKey, &image_quality_)); | 1485 options->GetInteger(keys::kQualityKey, &image_quality_)); |
| 1455 } | 1486 } |
| 1456 } | 1487 } |
| 1457 | 1488 |
| 1458 WebContents* web_contents = browser->GetSelectedWebContents(); | |
| 1459 if (!web_contents) { | |
| 1460 error_ = keys::kInternalVisibleTabCaptureError; | |
| 1461 return false; | |
| 1462 } | |
| 1463 | |
| 1464 // captureVisibleTab() can return an image containing sensitive information | 1489 // captureVisibleTab() can return an image containing sensitive information |
| 1465 // that the browser would otherwise protect. Ensure the extension has | 1490 // that the browser would otherwise protect. Ensure the extension has |
| 1466 // permission to do this. | 1491 // permission to do this. |
| 1467 if (!GetExtension()->CanCaptureVisiblePage(web_contents->GetURL(), &error_)) | 1492 if (!GetExtension()->CanCaptureVisiblePage(web_contents->GetURL(), &error_)) |
| 1468 return false; | 1493 return false; |
| 1469 | 1494 |
| 1470 RenderViewHost* render_view_host = web_contents->GetRenderViewHost(); | |
| 1471 | |
| 1472 // If a backing store is cached for the tab we want to capture, | 1495 // If a backing store is cached for the tab we want to capture, |
| 1473 // and it can be copied into a bitmap, then use it to generate the image. | 1496 // and it can be copied into a bitmap, then use it to generate the image. |
| 1497 RenderViewHost* render_view_host = web_contents->GetRenderViewHost(); |
| 1474 BackingStore* backing_store = render_view_host->GetBackingStore(false); | 1498 BackingStore* backing_store = render_view_host->GetBackingStore(false); |
| 1475 if (backing_store && CaptureSnapshotFromBackingStore(backing_store)) | 1499 if (backing_store && CaptureSnapshotFromBackingStore(backing_store)) |
| 1476 return true; | 1500 return true; |
| 1477 | 1501 |
| 1478 // Ask the renderer for a snapshot of the tab. | 1502 // Ask the renderer for a snapshot of the tab. |
| 1479 TabContentsWrapper* wrapper = browser->GetSelectedTabContentsWrapper(); | |
| 1480 wrapper->snapshot_tab_helper()->CaptureSnapshot(); | 1503 wrapper->snapshot_tab_helper()->CaptureSnapshot(); |
| 1481 registrar_.Add(this, | 1504 registrar_.Add(this, |
| 1482 chrome::NOTIFICATION_TAB_SNAPSHOT_TAKEN, | 1505 chrome::NOTIFICATION_TAB_SNAPSHOT_TAKEN, |
| 1483 content::Source<TabContentsWrapper>(wrapper)); | 1506 content::Source<TabContentsWrapper>(wrapper)); |
| 1484 AddRef(); // Balanced in CaptureVisibleTabFunction::Observe(). | 1507 AddRef(); // Balanced in CaptureVisibleTabFunction::Observe(). |
| 1485 | 1508 |
| 1486 return true; | 1509 return true; |
| 1487 } | 1510 } |
| 1488 | 1511 |
| 1489 // Build the image of a tab's contents out of a backing store. | 1512 // Build the image of a tab's contents out of a backing store. |
| (...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1647 // called for every API call the extension made. | 1670 // called for every API call the extension made. |
| 1648 GotLanguage(language); | 1671 GotLanguage(language); |
| 1649 } | 1672 } |
| 1650 | 1673 |
| 1651 void DetectTabLanguageFunction::GotLanguage(const std::string& language) { | 1674 void DetectTabLanguageFunction::GotLanguage(const std::string& language) { |
| 1652 result_.reset(Value::CreateStringValue(language.c_str())); | 1675 result_.reset(Value::CreateStringValue(language.c_str())); |
| 1653 SendResponse(true); | 1676 SendResponse(true); |
| 1654 | 1677 |
| 1655 Release(); // Balanced in Run() | 1678 Release(); // Balanced in Run() |
| 1656 } | 1679 } |
| OLD | NEW |