Chromium Code Reviews| 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 1013 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1024 error_ = keys::kNoHighlightedTabError; | 1024 error_ = keys::kNoHighlightedTabError; |
| 1025 return false; | 1025 return false; |
| 1026 } | 1026 } |
| 1027 | 1027 |
| 1028 selection.set_active(active_index); | 1028 selection.set_active(active_index); |
| 1029 browser->tabstrip_model()->SetSelectionFromModel(selection); | 1029 browser->tabstrip_model()->SetSelectionFromModel(selection); |
| 1030 result_.reset(ExtensionTabUtil::CreateWindowValue(browser, true)); | 1030 result_.reset(ExtensionTabUtil::CreateWindowValue(browser, true)); |
| 1031 return true; | 1031 return true; |
| 1032 } | 1032 } |
| 1033 | 1033 |
| 1034 UpdateTabFunction::UpdateTabFunction() { | 1034 UpdateTabFunction::UpdateTabFunction() |
| 1035 : web_contents_(NULL), | |
| 1036 tab_strip_(NULL), | |
| 1037 tab_index_(-1) { | |
| 1035 } | 1038 } |
| 1036 | 1039 |
| 1037 bool UpdateTabFunction::RunImpl() { | 1040 bool UpdateTabFunction::RunImpl() { |
| 1038 DictionaryValue* update_props = NULL; | 1041 DictionaryValue* update_props = NULL; |
| 1039 EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(1, &update_props)); | 1042 EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(1, &update_props)); |
| 1040 | 1043 |
| 1041 Value* tab_value = NULL; | 1044 Value* tab_value = NULL; |
| 1042 if (HasOptionalArgument(0)) { | 1045 if (HasOptionalArgument(0)) { |
| 1043 EXTENSION_FUNCTION_VALIDATE(args_->Get(0, &tab_value)); | 1046 EXTENSION_FUNCTION_VALIDATE(args_->Get(0, &tab_value)); |
| 1044 } | 1047 } |
| 1045 | 1048 |
| 1046 int tab_id = -1; | 1049 int tab_id = -1; |
| 1047 TabContentsWrapper* contents = NULL; | 1050 TabContentsWrapper* contents = NULL; |
| 1048 if (tab_value == NULL || tab_value->IsType(Value::TYPE_NULL)) { | 1051 if (tab_value == NULL || tab_value->IsType(Value::TYPE_NULL)) { |
| 1049 Browser* browser = GetCurrentBrowser(); | 1052 Browser* browser = GetCurrentBrowser(); |
| 1050 if (!browser) { | 1053 if (!browser) { |
| 1051 error_ = keys::kNoCurrentWindowError; | 1054 error_ = keys::kNoCurrentWindowError; |
| 1052 return false; | 1055 return false; |
| 1053 } | 1056 } |
| 1054 contents = browser->tabstrip_model()->GetActiveTabContents(); | 1057 contents = browser->tabstrip_model()->GetActiveTabContents(); |
| 1055 if (!contents) { | 1058 if (!contents) { |
| 1056 error_ = keys::kNoSelectedTabError; | 1059 error_ = keys::kNoSelectedTabError; |
| 1057 return false; | 1060 return false; |
| 1058 } | 1061 } |
| 1059 tab_id = ExtensionTabUtil::GetTabId(contents->web_contents()); | 1062 tab_id = ExtensionTabUtil::GetTabId(contents->web_contents()); |
| 1060 } else { | 1063 } else { |
| 1061 EXTENSION_FUNCTION_VALIDATE(tab_value->GetAsInteger(&tab_id)); | 1064 EXTENSION_FUNCTION_VALIDATE(tab_value->GetAsInteger(&tab_id)); |
| 1062 } | 1065 } |
| 1063 | 1066 |
| 1064 int tab_index = -1; | |
| 1065 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 |
| 1072 web_contents_ = contents->web_contents(); | |
|
Mihai Parparita -not on Chrome
2012/01/27 23:03:20
Is it safe to hold on to this pointer? I'm thinkin
jstritar
2012/01/30 16:28:05
Done. I also updated it so we don't need to hold o
| |
| 1073 NavigationController& controller = web_contents_->GetController(); | |
| 1071 | 1074 |
| 1072 // TODO(rafaelw): handle setting remaining tab properties: | 1075 // TODO(rafaelw): handle setting remaining tab properties: |
| 1073 // -title | 1076 // -title |
| 1074 // -favIconUrl | 1077 // -favIconUrl |
| 1075 | 1078 |
| 1079 // We wait to fire the callback when executing 'javascript:' URLs in tabs. | |
| 1080 bool is_async = false; | |
| 1081 | |
| 1076 // Navigate the tab to a new location if the url is different. | 1082 // Navigate the tab to a new location if the url is different. |
| 1077 std::string url_string; | 1083 std::string url_string; |
| 1078 if (update_props->HasKey(keys::kUrlKey)) { | 1084 if (update_props->HasKey(keys::kUrlKey)) { |
| 1079 EXTENSION_FUNCTION_VALIDATE(update_props->GetString( | 1085 EXTENSION_FUNCTION_VALIDATE(update_props->GetString( |
| 1080 keys::kUrlKey, &url_string)); | 1086 keys::kUrlKey, &url_string)); |
| 1081 GURL url = ResolvePossiblyRelativeURL(url_string, GetExtension()); | 1087 GURL url = ResolvePossiblyRelativeURL(url_string, GetExtension()); |
| 1082 | 1088 |
| 1083 if (!url.is_valid()) { | 1089 if (!url.is_valid()) { |
| 1084 error_ = ExtensionErrorUtils::FormatErrorMessage(keys::kInvalidUrlError, | 1090 error_ = ExtensionErrorUtils::FormatErrorMessage(keys::kInvalidUrlError, |
| 1085 url_string); | 1091 url_string); |
| 1086 return false; | 1092 return false; |
| 1087 } | 1093 } |
| 1088 | 1094 |
| 1089 // Don't let the extension crash the browser or renderers. | 1095 // Don't let the extension crash the browser or renderers. |
| 1090 if (IsCrashURL(url)) { | 1096 if (IsCrashURL(url)) { |
| 1091 error_ = keys::kNoCrashBrowserError; | 1097 error_ = keys::kNoCrashBrowserError; |
| 1092 return false; | 1098 return false; |
| 1093 } | 1099 } |
| 1094 | 1100 |
| 1095 // JavaScript URLs can do the same kinds of things as cross-origin XHR, so | 1101 // JavaScript URLs can do the same kinds of things as cross-origin XHR, so |
| 1096 // we need to check host permissions before allowing them. | 1102 // we need to check host permissions before allowing them. |
| 1097 if (url.SchemeIs(chrome::kJavaScriptScheme)) { | 1103 if (url.SchemeIs(chrome::kJavaScriptScheme)) { |
| 1098 if (!GetExtension()->CanExecuteScriptOnPage( | 1104 if (!GetExtension()->CanExecuteScriptOnPage( |
| 1099 contents->web_contents()->GetURL(), NULL, &error_)) { | 1105 web_contents_->GetURL(), NULL, &error_)) { |
| 1100 return false; | 1106 return false; |
| 1101 } | 1107 } |
| 1102 | 1108 |
| 1103 ExtensionMsg_ExecuteCode_Params params; | 1109 ExtensionMsg_ExecuteCode_Params params; |
| 1104 params.request_id = request_id(); | 1110 params.request_id = request_id(); |
| 1105 params.extension_id = extension_id(); | 1111 params.extension_id = extension_id(); |
| 1106 params.is_javascript = true; | 1112 params.is_javascript = true; |
| 1107 params.code = url.path(); | 1113 params.code = url.path(); |
| 1108 params.all_frames = false; | 1114 params.all_frames = false; |
| 1109 params.in_main_world = true; | 1115 params.in_main_world = true; |
| 1110 | 1116 |
| 1111 RenderViewHost* render_view_host = | 1117 RenderViewHost* render_view_host = web_contents_->GetRenderViewHost(); |
| 1112 contents->web_contents()->GetRenderViewHost(); | |
| 1113 render_view_host->Send( | 1118 render_view_host->Send( |
| 1114 new ExtensionMsg_ExecuteCode(render_view_host->routing_id(), | 1119 new ExtensionMsg_ExecuteCode(render_view_host->routing_id(), |
| 1115 params)); | 1120 params)); |
| 1116 | 1121 |
| 1117 Observe(contents->web_contents()); | 1122 Observe(web_contents_); |
| 1118 AddRef(); // balanced in Observe() | 1123 AddRef(); // Balanced in OnExecuteCodeFinished(). |
| 1119 | 1124 |
| 1120 return true; | 1125 is_async = true; |
| 1121 } | 1126 } |
| 1122 | 1127 |
| 1123 controller.LoadURL( | 1128 controller.LoadURL( |
| 1124 url, content::Referrer(), content::PAGE_TRANSITION_LINK, std::string()); | 1129 url, content::Referrer(), content::PAGE_TRANSITION_LINK, std::string()); |
| 1125 | 1130 |
| 1126 // The URL of a tab contents never actually changes to a JavaScript URL, so | 1131 // The URL of a tab contents never actually changes to a JavaScript URL, so |
| 1127 // this check only makes sense in other cases. | 1132 // this check only makes sense in other cases. |
| 1128 if (!url.SchemeIs(chrome::kJavaScriptScheme)) | 1133 if (!url.SchemeIs(chrome::kJavaScriptScheme)) |
| 1129 DCHECK_EQ(url.spec(), contents->web_contents()->GetURL().spec()); | 1134 DCHECK_EQ(url.spec(), web_contents_->GetURL().spec()); |
| 1130 } | 1135 } |
| 1131 | 1136 |
| 1132 bool active = false; | 1137 bool active = false; |
| 1133 // TODO(rafaelw): Setting |active| from js doesn't make much sense. | 1138 // TODO(rafaelw): Setting |active| from js doesn't make much sense. |
| 1134 // Move tab selection management up to window. | 1139 // Move tab selection management up to window. |
| 1135 if (update_props->HasKey(keys::kSelectedKey)) | 1140 if (update_props->HasKey(keys::kSelectedKey)) |
| 1136 EXTENSION_FUNCTION_VALIDATE(update_props->GetBoolean( | 1141 EXTENSION_FUNCTION_VALIDATE(update_props->GetBoolean( |
| 1137 keys::kSelectedKey, &active)); | 1142 keys::kSelectedKey, &active)); |
| 1138 | 1143 |
| 1139 // The 'active' property has replaced 'selected'. | 1144 // The 'active' property has replaced 'selected'. |
| 1140 if (update_props->HasKey(keys::kActiveKey)) | 1145 if (update_props->HasKey(keys::kActiveKey)) |
| 1141 EXTENSION_FUNCTION_VALIDATE(update_props->GetBoolean( | 1146 EXTENSION_FUNCTION_VALIDATE(update_props->GetBoolean( |
| 1142 keys::kActiveKey, &active)); | 1147 keys::kActiveKey, &active)); |
| 1143 | 1148 |
| 1144 if (active) { | 1149 if (active) { |
| 1145 if (tab_strip->active_index() != tab_index) { | 1150 if (tab_strip_->active_index() != tab_index_) { |
| 1146 tab_strip->ActivateTabAt(tab_index, false); | 1151 tab_strip_->ActivateTabAt(tab_index_, false); |
| 1147 DCHECK_EQ(contents, tab_strip->GetActiveTabContents()); | 1152 DCHECK_EQ(contents, tab_strip_->GetActiveTabContents()); |
| 1148 } | 1153 } |
| 1149 contents->web_contents()->Focus(); | 1154 web_contents_->Focus(); |
| 1150 } | 1155 } |
| 1151 | 1156 |
| 1152 bool highlighted = false; | 1157 bool highlighted = false; |
| 1153 if (update_props->HasKey(keys::kHighlightedKey)) { | 1158 if (update_props->HasKey(keys::kHighlightedKey)) { |
| 1154 EXTENSION_FUNCTION_VALIDATE(update_props->GetBoolean( | 1159 EXTENSION_FUNCTION_VALIDATE(update_props->GetBoolean( |
| 1155 keys::kHighlightedKey, &highlighted)); | 1160 keys::kHighlightedKey, &highlighted)); |
| 1156 if (highlighted != tab_strip->IsTabSelected(tab_index)) | 1161 if (highlighted != tab_strip_->IsTabSelected(tab_index_)) |
| 1157 tab_strip->ToggleSelectionAt(tab_index); | 1162 tab_strip_->ToggleSelectionAt(tab_index_); |
| 1158 } | 1163 } |
| 1159 | 1164 |
| 1160 bool pinned = false; | 1165 bool pinned = false; |
| 1161 if (update_props->HasKey(keys::kPinnedKey)) { | 1166 if (update_props->HasKey(keys::kPinnedKey)) { |
| 1162 EXTENSION_FUNCTION_VALIDATE(update_props->GetBoolean(keys::kPinnedKey, | 1167 EXTENSION_FUNCTION_VALIDATE(update_props->GetBoolean(keys::kPinnedKey, |
| 1163 &pinned)); | 1168 &pinned)); |
| 1164 tab_strip->SetTabPinned(tab_index, pinned); | 1169 tab_strip_->SetTabPinned(tab_index_, pinned); |
| 1165 | 1170 |
| 1166 // Update the tab index because it may move when being pinned. | 1171 // Update the tab index because it may move when being pinned. |
| 1167 tab_index = tab_strip->GetIndexOfTabContents(contents); | 1172 tab_index_ = tab_strip_->GetIndexOfTabContents(contents); |
| 1168 } | 1173 } |
| 1169 | 1174 |
| 1170 if (has_callback()) { | 1175 if (!is_async) { |
| 1171 if (GetExtension()->HasAPIPermission(ExtensionAPIPermission::kTab)) { | 1176 PopulateResult(); |
| 1172 result_.reset(ExtensionTabUtil::CreateTabValue(contents->web_contents(), | 1177 SendResponse(true); |
| 1173 tab_strip, | |
| 1174 tab_index)); | |
| 1175 } else { | |
| 1176 result_.reset(Value::CreateNullValue()); | |
| 1177 } | |
| 1178 } | 1178 } |
| 1179 return true; | |
| 1180 } | |
| 1179 | 1181 |
| 1180 SendResponse(true); | 1182 void UpdateTabFunction::PopulateResult() { |
| 1181 return true; | 1183 if (!has_callback()) |
| 1184 return; | |
| 1185 | |
| 1186 if (GetExtension()->HasAPIPermission(ExtensionAPIPermission::kTab)) { | |
| 1187 result_.reset(ExtensionTabUtil::CreateTabValue( | |
| 1188 web_contents_, tab_strip_, tab_index_)); | |
| 1189 } else { | |
| 1190 result_.reset(Value::CreateNullValue()); | |
| 1191 } | |
| 1182 } | 1192 } |
| 1183 | 1193 |
| 1184 bool UpdateTabFunction::OnMessageReceived(const IPC::Message& message) { | 1194 bool UpdateTabFunction::OnMessageReceived(const IPC::Message& message) { |
| 1185 if (message.type() != ExtensionHostMsg_ExecuteCodeFinished::ID) | 1195 if (message.type() != ExtensionHostMsg_ExecuteCodeFinished::ID) |
| 1186 return false; | 1196 return false; |
| 1187 | 1197 |
| 1188 int message_request_id = -1; | 1198 int message_request_id = -1; |
| 1189 void* iter = NULL; | 1199 void* iter = NULL; |
| 1190 if (!message.ReadInt(&iter, &message_request_id)) { | 1200 if (!message.ReadInt(&iter, &message_request_id)) { |
| 1191 NOTREACHED() << "malformed extension message"; | 1201 NOTREACHED() << "malformed extension message"; |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 1203 } | 1213 } |
| 1204 | 1214 |
| 1205 void UpdateTabFunction::OnExecuteCodeFinished(int request_id, | 1215 void UpdateTabFunction::OnExecuteCodeFinished(int request_id, |
| 1206 bool success, | 1216 bool success, |
| 1207 const std::string& error) { | 1217 const std::string& error) { |
| 1208 if (!error.empty()) { | 1218 if (!error.empty()) { |
| 1209 CHECK(!success); | 1219 CHECK(!success); |
| 1210 error_ = error; | 1220 error_ = error; |
| 1211 } | 1221 } |
| 1212 | 1222 |
| 1223 if (success) | |
| 1224 PopulateResult(); | |
| 1213 SendResponse(success); | 1225 SendResponse(success); |
| 1214 | 1226 |
| 1215 Observe(NULL); | 1227 Observe(NULL); |
| 1216 Release(); // balanced in Execute() | 1228 Release(); // Balanced in RunImpl(). |
| 1217 } | 1229 } |
| 1218 | 1230 |
| 1219 bool MoveTabsFunction::RunImpl() { | 1231 bool MoveTabsFunction::RunImpl() { |
| 1220 Value* tab_value = NULL; | 1232 Value* tab_value = NULL; |
| 1221 EXTENSION_FUNCTION_VALIDATE(args_->Get(0, &tab_value)); | 1233 EXTENSION_FUNCTION_VALIDATE(args_->Get(0, &tab_value)); |
| 1222 | 1234 |
| 1223 std::vector<int> tab_ids; | 1235 std::vector<int> tab_ids; |
| 1224 EXTENSION_FUNCTION_VALIDATE(ReadOneOrMoreIntegers(tab_value, &tab_ids)); | 1236 EXTENSION_FUNCTION_VALIDATE(ReadOneOrMoreIntegers(tab_value, &tab_ids)); |
| 1225 | 1237 |
| 1226 DictionaryValue* update_props = NULL; | 1238 DictionaryValue* update_props = NULL; |
| (...skipping 420 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1647 // called for every API call the extension made. | 1659 // called for every API call the extension made. |
| 1648 GotLanguage(language); | 1660 GotLanguage(language); |
| 1649 } | 1661 } |
| 1650 | 1662 |
| 1651 void DetectTabLanguageFunction::GotLanguage(const std::string& language) { | 1663 void DetectTabLanguageFunction::GotLanguage(const std::string& language) { |
| 1652 result_.reset(Value::CreateStringValue(language.c_str())); | 1664 result_.reset(Value::CreateStringValue(language.c_str())); |
| 1653 SendResponse(true); | 1665 SendResponse(true); |
| 1654 | 1666 |
| 1655 Release(); // Balanced in Run() | 1667 Release(); // Balanced in Run() |
| 1656 } | 1668 } |
| OLD | NEW |