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" |
11 #include "base/bind.h" | 11 #include "base/bind.h" |
12 #include "base/logging.h" | 12 #include "base/logging.h" |
13 #include "base/memory/ref_counted_memory.h" | 13 #include "base/memory/ref_counted_memory.h" |
14 #include "base/message_loop.h" | 14 #include "base/message_loop.h" |
15 #include "base/stl_util.h" | 15 #include "base/stl_util.h" |
16 #include "base/string16.h" | 16 #include "base/string16.h" |
17 #include "base/string_number_conversions.h" | 17 #include "base/string_number_conversions.h" |
18 #include "base/string_util.h" | 18 #include "base/string_util.h" |
19 #include "base/stringprintf.h" | 19 #include "base/stringprintf.h" |
20 #include "base/utf_string_conversions.h" | 20 #include "base/utf_string_conversions.h" |
21 #include "chrome/browser/extensions/extension_function_dispatcher.h" | 21 #include "chrome/browser/extensions/extension_function_dispatcher.h" |
22 #include "chrome/browser/extensions/extension_host.h" | 22 #include "chrome/browser/extensions/extension_host.h" |
23 #include "chrome/browser/extensions/extension_service.h" | 23 #include "chrome/browser/extensions/extension_service.h" |
24 #include "chrome/browser/extensions/extension_tab_helper.h" | 24 #include "chrome/browser/extensions/extension_tab_helper.h" |
25 #include "chrome/browser/extensions/extension_tab_util.h" | 25 #include "chrome/browser/extensions/extension_tab_util.h" |
26 #include "chrome/browser/extensions/extension_tabs_module_constants.h" | 26 #include "chrome/browser/extensions/extension_tabs_module_constants.h" |
27 #include "chrome/browser/extensions/extension_window_controller.h" | 27 #include "chrome/browser/extensions/extension_window_controller.h" |
28 #include "chrome/browser/extensions/extension_window_list.h" | 28 #include "chrome/browser/extensions/extension_window_list.h" |
| 29 #include "chrome/browser/extensions/script_executor.h" |
29 #include "chrome/browser/prefs/incognito_mode_prefs.h" | 30 #include "chrome/browser/prefs/incognito_mode_prefs.h" |
30 #include "chrome/browser/profiles/profile.h" | 31 #include "chrome/browser/profiles/profile.h" |
31 #include "chrome/browser/sessions/restore_tab_helper.h" | 32 #include "chrome/browser/sessions/restore_tab_helper.h" |
32 #include "chrome/browser/tabs/tab_strip_model.h" | 33 #include "chrome/browser/tabs/tab_strip_model.h" |
33 #include "chrome/browser/translate/translate_tab_helper.h" | 34 #include "chrome/browser/translate/translate_tab_helper.h" |
34 #include "chrome/browser/ui/browser.h" | 35 #include "chrome/browser/ui/browser.h" |
35 #include "chrome/browser/ui/browser_list.h" | 36 #include "chrome/browser/ui/browser_list.h" |
36 #include "chrome/browser/ui/browser_navigator.h" | 37 #include "chrome/browser/ui/browser_navigator.h" |
37 #include "chrome/browser/ui/browser_window.h" | 38 #include "chrome/browser/ui/browser_window.h" |
38 #include "chrome/browser/ui/extensions/shell_window.h" | 39 #include "chrome/browser/ui/extensions/shell_window.h" |
(...skipping 1130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1169 return false; | 1170 return false; |
1170 } | 1171 } |
1171 | 1172 |
1172 selection.set_active(active_index); | 1173 selection.set_active(active_index); |
1173 browser->tabstrip_model()->SetSelectionFromModel(selection); | 1174 browser->tabstrip_model()->SetSelectionFromModel(selection); |
1174 result_.reset( | 1175 result_.reset( |
1175 browser->extension_window_controller()->CreateWindowValueWithTabs()); | 1176 browser->extension_window_controller()->CreateWindowValueWithTabs()); |
1176 return true; | 1177 return true; |
1177 } | 1178 } |
1178 | 1179 |
1179 UpdateTabFunction::UpdateTabFunction() : web_contents_(NULL) { | 1180 UpdateTabFunction::UpdateTabFunction() : tab_contents_(NULL) { |
1180 } | 1181 } |
1181 | 1182 |
1182 bool UpdateTabFunction::RunImpl() { | 1183 bool UpdateTabFunction::RunImpl() { |
1183 DictionaryValue* update_props = NULL; | 1184 DictionaryValue* update_props = NULL; |
1184 EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(1, &update_props)); | 1185 EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(1, &update_props)); |
1185 | 1186 |
1186 Value* tab_value = NULL; | 1187 Value* tab_value = NULL; |
1187 if (HasOptionalArgument(0)) { | 1188 if (HasOptionalArgument(0)) { |
1188 EXTENSION_FUNCTION_VALIDATE(args_->Get(0, &tab_value)); | 1189 EXTENSION_FUNCTION_VALIDATE(args_->Get(0, &tab_value)); |
1189 } | 1190 } |
(...skipping 16 matching lines...) Expand all Loading... |
1206 EXTENSION_FUNCTION_VALIDATE(tab_value->GetAsInteger(&tab_id)); | 1207 EXTENSION_FUNCTION_VALIDATE(tab_value->GetAsInteger(&tab_id)); |
1207 } | 1208 } |
1208 | 1209 |
1209 int tab_index = -1; | 1210 int tab_index = -1; |
1210 TabStripModel* tab_strip = NULL; | 1211 TabStripModel* tab_strip = NULL; |
1211 if (!GetTabById(tab_id, profile(), include_incognito(), | 1212 if (!GetTabById(tab_id, profile(), include_incognito(), |
1212 NULL, &tab_strip, &contents, &tab_index, &error_)) { | 1213 NULL, &tab_strip, &contents, &tab_index, &error_)) { |
1213 return false; | 1214 return false; |
1214 } | 1215 } |
1215 | 1216 |
1216 web_contents_ = contents->web_contents(); | 1217 tab_contents_ = contents; |
1217 | 1218 |
1218 // TODO(rafaelw): handle setting remaining tab properties: | 1219 // TODO(rafaelw): handle setting remaining tab properties: |
1219 // -title | 1220 // -title |
1220 // -favIconUrl | 1221 // -favIconUrl |
1221 | 1222 |
1222 // Navigate the tab to a new location if the url is different. | 1223 // Navigate the tab to a new location if the url is different. |
1223 bool is_async = false; | 1224 bool is_async = false; |
1224 if (!UpdateURLIfPresent(update_props, &is_async)) | 1225 if (!UpdateURLIfPresent(update_props, &is_async)) |
1225 return false; | 1226 return false; |
1226 | 1227 |
1227 bool active = false; | 1228 bool active = false; |
1228 // TODO(rafaelw): Setting |active| from js doesn't make much sense. | 1229 // TODO(rafaelw): Setting |active| from js doesn't make much sense. |
1229 // Move tab selection management up to window. | 1230 // Move tab selection management up to window. |
1230 if (update_props->HasKey(keys::kSelectedKey)) | 1231 if (update_props->HasKey(keys::kSelectedKey)) |
1231 EXTENSION_FUNCTION_VALIDATE(update_props->GetBoolean( | 1232 EXTENSION_FUNCTION_VALIDATE(update_props->GetBoolean( |
1232 keys::kSelectedKey, &active)); | 1233 keys::kSelectedKey, &active)); |
1233 | 1234 |
1234 // The 'active' property has replaced 'selected'. | 1235 // The 'active' property has replaced 'selected'. |
1235 if (update_props->HasKey(keys::kActiveKey)) | 1236 if (update_props->HasKey(keys::kActiveKey)) |
1236 EXTENSION_FUNCTION_VALIDATE(update_props->GetBoolean( | 1237 EXTENSION_FUNCTION_VALIDATE(update_props->GetBoolean( |
1237 keys::kActiveKey, &active)); | 1238 keys::kActiveKey, &active)); |
1238 | 1239 |
1239 if (active) { | 1240 if (active) { |
1240 if (tab_strip->active_index() != tab_index) { | 1241 if (tab_strip->active_index() != tab_index) { |
1241 tab_strip->ActivateTabAt(tab_index, false); | 1242 tab_strip->ActivateTabAt(tab_index, false); |
1242 DCHECK_EQ(contents, tab_strip->GetActiveTabContents()); | 1243 DCHECK_EQ(contents, tab_strip->GetActiveTabContents()); |
1243 } | 1244 } |
1244 web_contents_->Focus(); | 1245 tab_contents_->web_contents()->Focus(); |
1245 } | 1246 } |
1246 | 1247 |
1247 if (update_props->HasKey(keys::kHighlightedKey)) { | 1248 if (update_props->HasKey(keys::kHighlightedKey)) { |
1248 bool highlighted = false; | 1249 bool highlighted = false; |
1249 EXTENSION_FUNCTION_VALIDATE(update_props->GetBoolean( | 1250 EXTENSION_FUNCTION_VALIDATE(update_props->GetBoolean( |
1250 keys::kHighlightedKey, &highlighted)); | 1251 keys::kHighlightedKey, &highlighted)); |
1251 if (highlighted != tab_strip->IsTabSelected(tab_index)) | 1252 if (highlighted != tab_strip->IsTabSelected(tab_index)) |
1252 tab_strip->ToggleSelectionAt(tab_index); | 1253 tab_strip->ToggleSelectionAt(tab_index); |
1253 } | 1254 } |
1254 | 1255 |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1304 // Don't let the extension crash the browser or renderers. | 1305 // Don't let the extension crash the browser or renderers. |
1305 if (ExtensionTabUtil::IsCrashURL(url)) { | 1306 if (ExtensionTabUtil::IsCrashURL(url)) { |
1306 error_ = keys::kNoCrashBrowserError; | 1307 error_ = keys::kNoCrashBrowserError; |
1307 return false; | 1308 return false; |
1308 } | 1309 } |
1309 | 1310 |
1310 // JavaScript URLs can do the same kinds of things as cross-origin XHR, so | 1311 // JavaScript URLs can do the same kinds of things as cross-origin XHR, so |
1311 // we need to check host permissions before allowing them. | 1312 // we need to check host permissions before allowing them. |
1312 if (url.SchemeIs(chrome::kJavaScriptScheme)) { | 1313 if (url.SchemeIs(chrome::kJavaScriptScheme)) { |
1313 if (!GetExtension()->CanExecuteScriptOnPage( | 1314 if (!GetExtension()->CanExecuteScriptOnPage( |
1314 web_contents_->GetURL(), NULL, &error_)) { | 1315 tab_contents_->web_contents()->GetURL(), NULL, &error_)) { |
1315 return false; | 1316 return false; |
1316 } | 1317 } |
1317 | 1318 |
1318 ExtensionMsg_ExecuteCode_Params params; | 1319 tab_contents_->extensions_script_executor()->ExecuteScript( |
1319 params.request_id = request_id(); | 1320 extension_id(), |
1320 params.extension_id = extension_id(); | 1321 true, |
1321 params.is_javascript = true; | 1322 url.path(), |
1322 params.code = url.path(); | 1323 false, |
1323 params.run_at = UserScript::DOCUMENT_IDLE; | 1324 UserScript::DOCUMENT_IDLE, |
1324 params.all_frames = false; | 1325 true, |
1325 params.in_main_world = true; | 1326 base::Bind(&UpdateTabFunction::OnExecuteCodeFinished, this)); |
1326 | |
1327 RenderViewHost* render_view_host = web_contents_->GetRenderViewHost(); | |
1328 render_view_host->Send( | |
1329 new ExtensionMsg_ExecuteCode(render_view_host->GetRoutingID(), params)); | |
1330 | |
1331 Observe(web_contents_); | |
1332 AddRef(); // Balanced in OnExecuteCodeFinished(). | |
1333 | 1327 |
1334 *is_async = true; | 1328 *is_async = true; |
1335 return true; | 1329 return true; |
1336 } | 1330 } |
1337 | 1331 |
1338 web_contents_->GetController().LoadURL( | 1332 tab_contents_->web_contents()->GetController().LoadURL( |
1339 url, content::Referrer(), content::PAGE_TRANSITION_LINK, std::string()); | 1333 url, content::Referrer(), content::PAGE_TRANSITION_LINK, std::string()); |
1340 | 1334 |
1341 // The URL of a tab contents never actually changes to a JavaScript URL, so | 1335 // The URL of a tab contents never actually changes to a JavaScript URL, so |
1342 // this check only makes sense in other cases. | 1336 // this check only makes sense in other cases. |
1343 if (!url.SchemeIs(chrome::kJavaScriptScheme)) | 1337 if (!url.SchemeIs(chrome::kJavaScriptScheme)) |
1344 DCHECK_EQ(url.spec(), web_contents_->GetURL().spec()); | 1338 DCHECK_EQ(url.spec(), tab_contents_->web_contents()->GetURL().spec()); |
1345 | 1339 |
1346 return true; | 1340 return true; |
1347 } | 1341 } |
1348 | 1342 |
1349 void UpdateTabFunction::PopulateResult() { | 1343 void UpdateTabFunction::PopulateResult() { |
1350 if (!has_callback()) | 1344 if (!has_callback()) |
1351 return; | 1345 return; |
1352 | 1346 |
1353 if (GetExtension()->HasAPIPermission(ExtensionAPIPermission::kTab) && | 1347 if (GetExtension()->HasAPIPermission(ExtensionAPIPermission::kTab)) { |
1354 web_contents_ != NULL) { | 1348 result_.reset( |
1355 result_.reset(ExtensionTabUtil::CreateTabValue(web_contents_)); | 1349 ExtensionTabUtil::CreateTabValue(tab_contents_->web_contents())); |
1356 } else { | 1350 } else { |
1357 result_.reset(Value::CreateNullValue()); | 1351 result_.reset(Value::CreateNullValue()); |
1358 } | 1352 } |
1359 } | 1353 } |
1360 | 1354 |
1361 void UpdateTabFunction::WebContentsDestroyed(WebContents* tab) { | 1355 void UpdateTabFunction::OnExecuteCodeFinished(bool success, |
1362 CHECK_EQ(tab, web_contents_); | |
1363 web_contents_ = NULL; | |
1364 } | |
1365 | |
1366 bool UpdateTabFunction::OnMessageReceived(const IPC::Message& message) { | |
1367 if (message.type() != ExtensionHostMsg_ExecuteCodeFinished::ID) | |
1368 return false; | |
1369 | |
1370 int message_request_id = -1; | |
1371 PickleIterator iter(message); | |
1372 if (!message.ReadInt(&iter, &message_request_id)) { | |
1373 NOTREACHED() << "malformed extension message"; | |
1374 return true; | |
1375 } | |
1376 | |
1377 if (message_request_id != request_id()) | |
1378 return false; | |
1379 | |
1380 IPC_BEGIN_MESSAGE_MAP(UpdateTabFunction, message) | |
1381 IPC_MESSAGE_HANDLER(ExtensionHostMsg_ExecuteCodeFinished, | |
1382 OnExecuteCodeFinished) | |
1383 IPC_END_MESSAGE_MAP() | |
1384 return true; | |
1385 } | |
1386 | |
1387 void UpdateTabFunction::OnExecuteCodeFinished(int request_id, | |
1388 bool success, | |
1389 const std::string& error) { | 1356 const std::string& error) { |
1390 if (!error.empty()) { | 1357 if (!error.empty()) { |
1391 CHECK(!success); | 1358 CHECK(!success); |
1392 error_ = error; | 1359 error_ = error; |
1393 } | 1360 } |
1394 | 1361 |
1395 if (success) | 1362 if (success) |
1396 PopulateResult(); | 1363 PopulateResult(); |
1397 SendResponse(success); | 1364 SendResponse(success); |
1398 | |
1399 Observe(NULL); | |
1400 Release(); // Balanced in UpdateURLIfPresent(). | |
1401 } | 1365 } |
1402 | 1366 |
1403 bool MoveTabsFunction::RunImpl() { | 1367 bool MoveTabsFunction::RunImpl() { |
1404 Value* tab_value = NULL; | 1368 Value* tab_value = NULL; |
1405 EXTENSION_FUNCTION_VALIDATE(args_->Get(0, &tab_value)); | 1369 EXTENSION_FUNCTION_VALIDATE(args_->Get(0, &tab_value)); |
1406 | 1370 |
1407 std::vector<int> tab_ids; | 1371 std::vector<int> tab_ids; |
1408 EXTENSION_FUNCTION_VALIDATE(ReadOneOrMoreIntegers(tab_value, &tab_ids)); | 1372 EXTENSION_FUNCTION_VALIDATE(ReadOneOrMoreIntegers(tab_value, &tab_ids)); |
1409 | 1373 |
1410 DictionaryValue* update_props = NULL; | 1374 DictionaryValue* update_props = NULL; |
(...skipping 436 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1847 // called for every API call the extension made. | 1811 // called for every API call the extension made. |
1848 GotLanguage(language); | 1812 GotLanguage(language); |
1849 } | 1813 } |
1850 | 1814 |
1851 void DetectTabLanguageFunction::GotLanguage(const std::string& language) { | 1815 void DetectTabLanguageFunction::GotLanguage(const std::string& language) { |
1852 result_.reset(Value::CreateStringValue(language.c_str())); | 1816 result_.reset(Value::CreateStringValue(language.c_str())); |
1853 SendResponse(true); | 1817 SendResponse(true); |
1854 | 1818 |
1855 Release(); // Balanced in Run() | 1819 Release(); // Balanced in Run() |
1856 } | 1820 } |
OLD | NEW |