| 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 1040 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1051 error_ = keys::kNoHighlightedTabError; | 1051 error_ = keys::kNoHighlightedTabError; |
| 1052 return false; | 1052 return false; |
| 1053 } | 1053 } |
| 1054 | 1054 |
| 1055 selection.set_active(active_index); | 1055 selection.set_active(active_index); |
| 1056 browser->tabstrip_model()->SetSelectionFromModel(selection); | 1056 browser->tabstrip_model()->SetSelectionFromModel(selection); |
| 1057 result_.reset(ExtensionTabUtil::CreateWindowValue(browser, true)); | 1057 result_.reset(ExtensionTabUtil::CreateWindowValue(browser, true)); |
| 1058 return true; | 1058 return true; |
| 1059 } | 1059 } |
| 1060 | 1060 |
| 1061 UpdateTabFunction::UpdateTabFunction() { | 1061 UpdateTabFunction::UpdateTabFunction() : web_contents_(NULL) { |
| 1062 } | 1062 } |
| 1063 | 1063 |
| 1064 bool UpdateTabFunction::RunImpl() { | 1064 bool UpdateTabFunction::RunImpl() { |
| 1065 DictionaryValue* update_props = NULL; | 1065 DictionaryValue* update_props = NULL; |
| 1066 EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(1, &update_props)); | 1066 EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(1, &update_props)); |
| 1067 | 1067 |
| 1068 Value* tab_value = NULL; | 1068 Value* tab_value = NULL; |
| 1069 if (HasOptionalArgument(0)) { | 1069 if (HasOptionalArgument(0)) { |
| 1070 EXTENSION_FUNCTION_VALIDATE(args_->Get(0, &tab_value)); | 1070 EXTENSION_FUNCTION_VALIDATE(args_->Get(0, &tab_value)); |
| 1071 } | 1071 } |
| (...skipping 15 matching lines...) Expand all Loading... |
| 1087 } else { | 1087 } else { |
| 1088 EXTENSION_FUNCTION_VALIDATE(tab_value->GetAsInteger(&tab_id)); | 1088 EXTENSION_FUNCTION_VALIDATE(tab_value->GetAsInteger(&tab_id)); |
| 1089 } | 1089 } |
| 1090 | 1090 |
| 1091 int tab_index = -1; | 1091 int tab_index = -1; |
| 1092 TabStripModel* tab_strip = NULL; | 1092 TabStripModel* tab_strip = NULL; |
| 1093 if (!GetTabById(tab_id, profile(), include_incognito(), | 1093 if (!GetTabById(tab_id, profile(), include_incognito(), |
| 1094 NULL, &tab_strip, &contents, &tab_index, &error_)) { | 1094 NULL, &tab_strip, &contents, &tab_index, &error_)) { |
| 1095 return false; | 1095 return false; |
| 1096 } | 1096 } |
| 1097 NavigationController& controller = contents->web_contents()->GetController(); | 1097 |
| 1098 web_contents_ = contents->web_contents(); |
| 1099 NavigationController& controller = web_contents_->GetController(); |
| 1098 | 1100 |
| 1099 // TODO(rafaelw): handle setting remaining tab properties: | 1101 // TODO(rafaelw): handle setting remaining tab properties: |
| 1100 // -title | 1102 // -title |
| 1101 // -favIconUrl | 1103 // -favIconUrl |
| 1102 | 1104 |
| 1105 // We wait to fire the callback when executing 'javascript:' URLs in tabs. |
| 1106 bool is_async = false; |
| 1107 |
| 1103 // Navigate the tab to a new location if the url is different. | 1108 // Navigate the tab to a new location if the url is different. |
| 1104 std::string url_string; | 1109 std::string url_string; |
| 1105 if (update_props->HasKey(keys::kUrlKey)) { | 1110 if (update_props->HasKey(keys::kUrlKey)) { |
| 1106 EXTENSION_FUNCTION_VALIDATE(update_props->GetString( | 1111 EXTENSION_FUNCTION_VALIDATE(update_props->GetString( |
| 1107 keys::kUrlKey, &url_string)); | 1112 keys::kUrlKey, &url_string)); |
| 1108 GURL url = ResolvePossiblyRelativeURL(url_string, GetExtension()); | 1113 GURL url = ResolvePossiblyRelativeURL(url_string, GetExtension()); |
| 1109 | 1114 |
| 1110 if (!url.is_valid()) { | 1115 if (!url.is_valid()) { |
| 1111 error_ = ExtensionErrorUtils::FormatErrorMessage(keys::kInvalidUrlError, | 1116 error_ = ExtensionErrorUtils::FormatErrorMessage(keys::kInvalidUrlError, |
| 1112 url_string); | 1117 url_string); |
| 1113 return false; | 1118 return false; |
| 1114 } | 1119 } |
| 1115 | 1120 |
| 1116 // Don't let the extension crash the browser or renderers. | 1121 // Don't let the extension crash the browser or renderers. |
| 1117 if (IsCrashURL(url)) { | 1122 if (IsCrashURL(url)) { |
| 1118 error_ = keys::kNoCrashBrowserError; | 1123 error_ = keys::kNoCrashBrowserError; |
| 1119 return false; | 1124 return false; |
| 1120 } | 1125 } |
| 1121 | 1126 |
| 1122 // JavaScript URLs can do the same kinds of things as cross-origin XHR, so | 1127 // JavaScript URLs can do the same kinds of things as cross-origin XHR, so |
| 1123 // we need to check host permissions before allowing them. | 1128 // we need to check host permissions before allowing them. |
| 1124 if (url.SchemeIs(chrome::kJavaScriptScheme)) { | 1129 if (url.SchemeIs(chrome::kJavaScriptScheme)) { |
| 1125 if (!GetExtension()->CanExecuteScriptOnPage( | 1130 if (!GetExtension()->CanExecuteScriptOnPage( |
| 1126 contents->web_contents()->GetURL(), NULL, &error_)) { | 1131 web_contents_->GetURL(), NULL, &error_)) { |
| 1127 return false; | 1132 return false; |
| 1128 } | 1133 } |
| 1129 | 1134 |
| 1130 ExtensionMsg_ExecuteCode_Params params; | 1135 ExtensionMsg_ExecuteCode_Params params; |
| 1131 params.request_id = request_id(); | 1136 params.request_id = request_id(); |
| 1132 params.extension_id = extension_id(); | 1137 params.extension_id = extension_id(); |
| 1133 params.is_javascript = true; | 1138 params.is_javascript = true; |
| 1134 params.code = url.path(); | 1139 params.code = url.path(); |
| 1135 params.all_frames = false; | 1140 params.all_frames = false; |
| 1136 params.in_main_world = true; | 1141 params.in_main_world = true; |
| 1137 | 1142 |
| 1138 RenderViewHost* render_view_host = | 1143 RenderViewHost* render_view_host = web_contents_->GetRenderViewHost(); |
| 1139 contents->web_contents()->GetRenderViewHost(); | |
| 1140 render_view_host->Send( | 1144 render_view_host->Send( |
| 1141 new ExtensionMsg_ExecuteCode(render_view_host->routing_id(), | 1145 new ExtensionMsg_ExecuteCode(render_view_host->routing_id(), |
| 1142 params)); | 1146 params)); |
| 1143 | 1147 |
| 1144 Observe(contents->web_contents()); | 1148 Observe(web_contents_); |
| 1145 AddRef(); // balanced in Observe() | 1149 AddRef(); // Balanced in OnExecuteCodeFinished(). |
| 1146 | 1150 |
| 1147 return true; | 1151 is_async = true; |
| 1148 } | 1152 } |
| 1149 | 1153 |
| 1150 controller.LoadURL( | 1154 controller.LoadURL( |
| 1151 url, content::Referrer(), content::PAGE_TRANSITION_LINK, std::string()); | 1155 url, content::Referrer(), content::PAGE_TRANSITION_LINK, std::string()); |
| 1152 | 1156 |
| 1153 // The URL of a tab contents never actually changes to a JavaScript URL, so | 1157 // The URL of a tab contents never actually changes to a JavaScript URL, so |
| 1154 // this check only makes sense in other cases. | 1158 // this check only makes sense in other cases. |
| 1155 if (!url.SchemeIs(chrome::kJavaScriptScheme)) | 1159 if (!url.SchemeIs(chrome::kJavaScriptScheme)) |
| 1156 DCHECK_EQ(url.spec(), contents->web_contents()->GetURL().spec()); | 1160 DCHECK_EQ(url.spec(), web_contents_->GetURL().spec()); |
| 1157 } | 1161 } |
| 1158 | 1162 |
| 1159 bool active = false; | 1163 bool active = false; |
| 1160 // TODO(rafaelw): Setting |active| from js doesn't make much sense. | 1164 // TODO(rafaelw): Setting |active| from js doesn't make much sense. |
| 1161 // Move tab selection management up to window. | 1165 // Move tab selection management up to window. |
| 1162 if (update_props->HasKey(keys::kSelectedKey)) | 1166 if (update_props->HasKey(keys::kSelectedKey)) |
| 1163 EXTENSION_FUNCTION_VALIDATE(update_props->GetBoolean( | 1167 EXTENSION_FUNCTION_VALIDATE(update_props->GetBoolean( |
| 1164 keys::kSelectedKey, &active)); | 1168 keys::kSelectedKey, &active)); |
| 1165 | 1169 |
| 1166 // The 'active' property has replaced 'selected'. | 1170 // The 'active' property has replaced 'selected'. |
| 1167 if (update_props->HasKey(keys::kActiveKey)) | 1171 if (update_props->HasKey(keys::kActiveKey)) |
| 1168 EXTENSION_FUNCTION_VALIDATE(update_props->GetBoolean( | 1172 EXTENSION_FUNCTION_VALIDATE(update_props->GetBoolean( |
| 1169 keys::kActiveKey, &active)); | 1173 keys::kActiveKey, &active)); |
| 1170 | 1174 |
| 1171 if (active) { | 1175 if (active) { |
| 1172 if (tab_strip->active_index() != tab_index) { | 1176 if (tab_strip->active_index() != tab_index) { |
| 1173 tab_strip->ActivateTabAt(tab_index, false); | 1177 tab_strip->ActivateTabAt(tab_index, false); |
| 1174 DCHECK_EQ(contents, tab_strip->GetActiveTabContents()); | 1178 DCHECK_EQ(contents, tab_strip->GetActiveTabContents()); |
| 1175 } | 1179 } |
| 1176 contents->web_contents()->Focus(); | 1180 web_contents_->Focus(); |
| 1177 } | 1181 } |
| 1178 | 1182 |
| 1179 if (update_props->HasKey(keys::kHighlightedKey)) { | 1183 if (update_props->HasKey(keys::kHighlightedKey)) { |
| 1180 bool highlighted = false; | 1184 bool highlighted = false; |
| 1181 EXTENSION_FUNCTION_VALIDATE(update_props->GetBoolean( | 1185 EXTENSION_FUNCTION_VALIDATE(update_props->GetBoolean( |
| 1182 keys::kHighlightedKey, &highlighted)); | 1186 keys::kHighlightedKey, &highlighted)); |
| 1183 if (highlighted != tab_strip->IsTabSelected(tab_index)) | 1187 if (highlighted != tab_strip->IsTabSelected(tab_index)) |
| 1184 tab_strip->ToggleSelectionAt(tab_index); | 1188 tab_strip->ToggleSelectionAt(tab_index); |
| 1185 } | 1189 } |
| 1186 | 1190 |
| (...skipping 15 matching lines...) Expand all Loading... |
| 1202 TabContentsWrapper* opener_contents = NULL; | 1206 TabContentsWrapper* opener_contents = NULL; |
| 1203 if (!ExtensionTabUtil::GetTabById( | 1207 if (!ExtensionTabUtil::GetTabById( |
| 1204 opener_id, profile(), include_incognito(), | 1208 opener_id, profile(), include_incognito(), |
| 1205 NULL, NULL, &opener_contents, NULL)) | 1209 NULL, NULL, &opener_contents, NULL)) |
| 1206 return false; | 1210 return false; |
| 1207 | 1211 |
| 1208 tab_strip->SetOpenerOfTabContentsAt( | 1212 tab_strip->SetOpenerOfTabContentsAt( |
| 1209 tab_index, &opener_contents->web_contents()->GetController()); | 1213 tab_index, &opener_contents->web_contents()->GetController()); |
| 1210 } | 1214 } |
| 1211 | 1215 |
| 1212 if (has_callback()) { | 1216 if (!is_async) { |
| 1213 if (GetExtension()->HasAPIPermission(ExtensionAPIPermission::kTab)) { | 1217 PopulateResult(); |
| 1214 result_.reset(ExtensionTabUtil::CreateTabValue(contents->web_contents(), | 1218 SendResponse(true); |
| 1215 tab_strip, | |
| 1216 tab_index)); | |
| 1217 } else { | |
| 1218 result_.reset(Value::CreateNullValue()); | |
| 1219 } | |
| 1220 } | 1219 } |
| 1220 return true; |
| 1221 } |
| 1221 | 1222 |
| 1222 SendResponse(true); | 1223 void UpdateTabFunction::PopulateResult() { |
| 1223 return true; | 1224 if (!has_callback()) |
| 1225 return; |
| 1226 |
| 1227 if (GetExtension()->HasAPIPermission(ExtensionAPIPermission::kTab) && |
| 1228 web_contents_ != NULL) { |
| 1229 result_.reset(ExtensionTabUtil::CreateTabValue(web_contents_)); |
| 1230 } else { |
| 1231 result_.reset(Value::CreateNullValue()); |
| 1232 } |
| 1233 } |
| 1234 |
| 1235 void UpdateTabFunction::WebContentsDestroyed(WebContents* tab) { |
| 1236 CHECK_EQ(tab, web_contents_); |
| 1237 web_contents_ = NULL; |
| 1224 } | 1238 } |
| 1225 | 1239 |
| 1226 bool UpdateTabFunction::OnMessageReceived(const IPC::Message& message) { | 1240 bool UpdateTabFunction::OnMessageReceived(const IPC::Message& message) { |
| 1227 if (message.type() != ExtensionHostMsg_ExecuteCodeFinished::ID) | 1241 if (message.type() != ExtensionHostMsg_ExecuteCodeFinished::ID) |
| 1228 return false; | 1242 return false; |
| 1229 | 1243 |
| 1230 int message_request_id = -1; | 1244 int message_request_id = -1; |
| 1231 void* iter = NULL; | 1245 void* iter = NULL; |
| 1232 if (!message.ReadInt(&iter, &message_request_id)) { | 1246 if (!message.ReadInt(&iter, &message_request_id)) { |
| 1233 NOTREACHED() << "malformed extension message"; | 1247 NOTREACHED() << "malformed extension message"; |
| (...skipping 11 matching lines...) Expand all Loading... |
| 1245 } | 1259 } |
| 1246 | 1260 |
| 1247 void UpdateTabFunction::OnExecuteCodeFinished(int request_id, | 1261 void UpdateTabFunction::OnExecuteCodeFinished(int request_id, |
| 1248 bool success, | 1262 bool success, |
| 1249 const std::string& error) { | 1263 const std::string& error) { |
| 1250 if (!error.empty()) { | 1264 if (!error.empty()) { |
| 1251 CHECK(!success); | 1265 CHECK(!success); |
| 1252 error_ = error; | 1266 error_ = error; |
| 1253 } | 1267 } |
| 1254 | 1268 |
| 1269 if (success) |
| 1270 PopulateResult(); |
| 1255 SendResponse(success); | 1271 SendResponse(success); |
| 1256 | 1272 |
| 1257 Observe(NULL); | 1273 Observe(NULL); |
| 1258 Release(); // balanced in Execute() | 1274 Release(); // Balanced in RunImpl(). |
| 1259 } | 1275 } |
| 1260 | 1276 |
| 1261 bool MoveTabsFunction::RunImpl() { | 1277 bool MoveTabsFunction::RunImpl() { |
| 1262 Value* tab_value = NULL; | 1278 Value* tab_value = NULL; |
| 1263 EXTENSION_FUNCTION_VALIDATE(args_->Get(0, &tab_value)); | 1279 EXTENSION_FUNCTION_VALIDATE(args_->Get(0, &tab_value)); |
| 1264 | 1280 |
| 1265 std::vector<int> tab_ids; | 1281 std::vector<int> tab_ids; |
| 1266 EXTENSION_FUNCTION_VALIDATE(ReadOneOrMoreIntegers(tab_value, &tab_ids)); | 1282 EXTENSION_FUNCTION_VALIDATE(ReadOneOrMoreIntegers(tab_value, &tab_ids)); |
| 1267 | 1283 |
| 1268 DictionaryValue* update_props = NULL; | 1284 DictionaryValue* update_props = NULL; |
| (...skipping 420 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1689 // called for every API call the extension made. | 1705 // called for every API call the extension made. |
| 1690 GotLanguage(language); | 1706 GotLanguage(language); |
| 1691 } | 1707 } |
| 1692 | 1708 |
| 1693 void DetectTabLanguageFunction::GotLanguage(const std::string& language) { | 1709 void DetectTabLanguageFunction::GotLanguage(const std::string& language) { |
| 1694 result_.reset(Value::CreateStringValue(language.c_str())); | 1710 result_.reset(Value::CreateStringValue(language.c_str())); |
| 1695 SendResponse(true); | 1711 SendResponse(true); |
| 1696 | 1712 |
| 1697 Release(); // Balanced in Run() | 1713 Release(); // Balanced in Run() |
| 1698 } | 1714 } |
| OLD | NEW |