OLD | NEW |
1 // Copyright 2012 The Chromium Authors. All rights reserved. | 1 // Copyright 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/task_manager/task_manager_resource_providers.h" | 5 #include "chrome/browser/task_manager/task_manager_resource_providers.h" |
6 | 6 |
7 #include <string> | 7 #include <string> |
8 | 8 |
9 #include "base/basictypes.h" | 9 #include "base/basictypes.h" |
10 #include "base/bind.h" | 10 #include "base/bind.h" |
(...skipping 26 matching lines...) Expand all Loading... |
37 #include "chrome/browser/tab_contents/background_contents.h" | 37 #include "chrome/browser/tab_contents/background_contents.h" |
38 #include "chrome/browser/tab_contents/tab_util.h" | 38 #include "chrome/browser/tab_contents/tab_util.h" |
39 #include "chrome/browser/ui/browser.h" | 39 #include "chrome/browser/ui/browser.h" |
40 #include "chrome/browser/ui/browser_finder.h" | 40 #include "chrome/browser/ui/browser_finder.h" |
41 #include "chrome/browser/ui/browser_instant_controller.h" | 41 #include "chrome/browser/ui/browser_instant_controller.h" |
42 #include "chrome/browser/ui/browser_iterator.h" | 42 #include "chrome/browser/ui/browser_iterator.h" |
43 #include "chrome/browser/ui/panels/panel.h" | 43 #include "chrome/browser/ui/panels/panel.h" |
44 #include "chrome/browser/ui/panels/panel_manager.h" | 44 #include "chrome/browser/ui/panels/panel_manager.h" |
45 #include "chrome/browser/ui/tab_contents/tab_contents_iterator.h" | 45 #include "chrome/browser/ui/tab_contents/tab_contents_iterator.h" |
46 #include "chrome/browser/view_type_utils.h" | 46 #include "chrome/browser/view_type_utils.h" |
| 47 #include "chrome/common/chrome_process_type.h" |
47 #include "chrome/common/chrome_notification_types.h" | 48 #include "chrome/common/chrome_notification_types.h" |
48 #include "chrome/common/chrome_switches.h" | 49 #include "chrome/common/chrome_switches.h" |
49 #include "chrome/common/extensions/extension.h" | 50 #include "chrome/common/extensions/extension.h" |
50 #include "chrome/common/render_messages.h" | 51 #include "chrome/common/render_messages.h" |
51 #include "chrome/common/url_constants.h" | 52 #include "chrome/common/url_constants.h" |
52 #include "content/public/browser/browser_child_process_host_iterator.h" | 53 #include "content/public/browser/browser_child_process_host_iterator.h" |
53 #include "content/public/browser/browser_thread.h" | 54 #include "content/public/browser/browser_thread.h" |
54 #include "content/public/browser/child_process_data.h" | 55 #include "content/public/browser/child_process_data.h" |
55 #include "content/public/browser/notification_service.h" | 56 #include "content/public/browser/notification_service.h" |
56 #include "content/public/browser/render_process_host.h" | 57 #include "content/public/browser/render_process_host.h" |
(...skipping 982 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1039 return; | 1040 return; |
1040 } | 1041 } |
1041 } | 1042 } |
1042 | 1043 |
1043 //////////////////////////////////////////////////////////////////////////////// | 1044 //////////////////////////////////////////////////////////////////////////////// |
1044 // TaskManagerChildProcessResource class | 1045 // TaskManagerChildProcessResource class |
1045 //////////////////////////////////////////////////////////////////////////////// | 1046 //////////////////////////////////////////////////////////////////////////////// |
1046 gfx::ImageSkia* TaskManagerChildProcessResource::default_icon_ = NULL; | 1047 gfx::ImageSkia* TaskManagerChildProcessResource::default_icon_ = NULL; |
1047 | 1048 |
1048 TaskManagerChildProcessResource::TaskManagerChildProcessResource( | 1049 TaskManagerChildProcessResource::TaskManagerChildProcessResource( |
1049 content::ProcessType type, | 1050 int process_type, |
1050 const string16& name, | 1051 const string16& name, |
1051 base::ProcessHandle handle, | 1052 base::ProcessHandle handle, |
1052 int unique_process_id) | 1053 int unique_process_id) |
1053 : type_(type), | 1054 : process_type_(process_type), |
1054 name_(name), | 1055 name_(name), |
1055 handle_(handle), | 1056 handle_(handle), |
1056 unique_process_id_(unique_process_id), | 1057 unique_process_id_(unique_process_id), |
1057 network_usage_support_(false) { | 1058 network_usage_support_(false) { |
1058 // We cache the process id because it's not cheap to calculate, and it won't | 1059 // We cache the process id because it's not cheap to calculate, and it won't |
1059 // be available when we get the plugin disconnected notification. | 1060 // be available when we get the plugin disconnected notification. |
1060 pid_ = base::GetProcId(handle); | 1061 pid_ = base::GetProcId(handle); |
1061 if (!default_icon_) { | 1062 if (!default_icon_) { |
1062 ResourceBundle& rb = ResourceBundle::GetSharedInstance(); | 1063 ResourceBundle& rb = ResourceBundle::GetSharedInstance(); |
1063 default_icon_ = rb.GetImageSkiaNamed(IDR_PLUGINS_FAVICON); | 1064 default_icon_ = rb.GetImageSkiaNamed(IDR_PLUGINS_FAVICON); |
(...skipping 24 matching lines...) Expand all Loading... |
1088 return handle_; | 1089 return handle_; |
1089 } | 1090 } |
1090 | 1091 |
1091 int TaskManagerChildProcessResource::GetUniqueChildProcessId() const { | 1092 int TaskManagerChildProcessResource::GetUniqueChildProcessId() const { |
1092 return unique_process_id_; | 1093 return unique_process_id_; |
1093 } | 1094 } |
1094 | 1095 |
1095 TaskManager::Resource::Type TaskManagerChildProcessResource::GetType() const { | 1096 TaskManager::Resource::Type TaskManagerChildProcessResource::GetType() const { |
1096 // Translate types to TaskManager::ResourceType, since ChildProcessData's type | 1097 // Translate types to TaskManager::ResourceType, since ChildProcessData's type |
1097 // is not available for all TaskManager resources. | 1098 // is not available for all TaskManager resources. |
1098 switch (type_) { | 1099 switch (process_type_) { |
1099 case content::PROCESS_TYPE_PLUGIN: | 1100 case content::PROCESS_TYPE_PLUGIN: |
1100 case content::PROCESS_TYPE_PPAPI_PLUGIN: | 1101 case content::PROCESS_TYPE_PPAPI_PLUGIN: |
1101 case content::PROCESS_TYPE_PPAPI_BROKER: | 1102 case content::PROCESS_TYPE_PPAPI_BROKER: |
1102 return TaskManager::Resource::PLUGIN; | 1103 return TaskManager::Resource::PLUGIN; |
1103 case content::PROCESS_TYPE_NACL_LOADER: | |
1104 case content::PROCESS_TYPE_NACL_BROKER: | |
1105 return TaskManager::Resource::NACL; | |
1106 case content::PROCESS_TYPE_UTILITY: | 1104 case content::PROCESS_TYPE_UTILITY: |
1107 return TaskManager::Resource::UTILITY; | 1105 return TaskManager::Resource::UTILITY; |
1108 case content::PROCESS_TYPE_PROFILE_IMPORT: | |
1109 return TaskManager::Resource::PROFILE_IMPORT; | |
1110 case content::PROCESS_TYPE_ZYGOTE: | 1106 case content::PROCESS_TYPE_ZYGOTE: |
1111 return TaskManager::Resource::ZYGOTE; | 1107 return TaskManager::Resource::ZYGOTE; |
1112 case content::PROCESS_TYPE_SANDBOX_HELPER: | 1108 case content::PROCESS_TYPE_SANDBOX_HELPER: |
1113 return TaskManager::Resource::SANDBOX_HELPER; | 1109 return TaskManager::Resource::SANDBOX_HELPER; |
1114 case content::PROCESS_TYPE_GPU: | 1110 case content::PROCESS_TYPE_GPU: |
1115 return TaskManager::Resource::GPU; | 1111 return TaskManager::Resource::GPU; |
| 1112 case PROCESS_TYPE_PROFILE_IMPORT: |
| 1113 return TaskManager::Resource::PROFILE_IMPORT; |
| 1114 case PROCESS_TYPE_NACL_LOADER: |
| 1115 case PROCESS_TYPE_NACL_BROKER: |
| 1116 return TaskManager::Resource::NACL; |
1116 default: | 1117 default: |
1117 return TaskManager::Resource::UNKNOWN; | 1118 return TaskManager::Resource::UNKNOWN; |
1118 } | 1119 } |
1119 } | 1120 } |
1120 | 1121 |
1121 bool TaskManagerChildProcessResource::SupportNetworkUsage() const { | 1122 bool TaskManagerChildProcessResource::SupportNetworkUsage() const { |
1122 return network_usage_support_; | 1123 return network_usage_support_; |
1123 } | 1124 } |
1124 | 1125 |
1125 void TaskManagerChildProcessResource::SetSupportNetworkUsage() { | 1126 void TaskManagerChildProcessResource::SetSupportNetworkUsage() { |
1126 network_usage_support_ = true; | 1127 network_usage_support_ = true; |
1127 } | 1128 } |
1128 | 1129 |
1129 string16 TaskManagerChildProcessResource::GetLocalizedTitle() const { | 1130 string16 TaskManagerChildProcessResource::GetLocalizedTitle() const { |
1130 string16 title = name_; | 1131 string16 title = name_; |
1131 if (title.empty()) { | 1132 if (title.empty()) { |
1132 switch (type_) { | 1133 switch (process_type_) { |
1133 case content::PROCESS_TYPE_PLUGIN: | 1134 case content::PROCESS_TYPE_PLUGIN: |
1134 case content::PROCESS_TYPE_PPAPI_PLUGIN: | 1135 case content::PROCESS_TYPE_PPAPI_PLUGIN: |
1135 case content::PROCESS_TYPE_PPAPI_BROKER: | 1136 case content::PROCESS_TYPE_PPAPI_BROKER: |
1136 title = l10n_util::GetStringUTF16(IDS_TASK_MANAGER_UNKNOWN_PLUGIN_NAME); | 1137 title = l10n_util::GetStringUTF16(IDS_TASK_MANAGER_UNKNOWN_PLUGIN_NAME); |
1137 break; | 1138 break; |
1138 default: | 1139 default: |
1139 // Nothing to do for non-plugin processes. | 1140 // Nothing to do for non-plugin processes. |
1140 break; | 1141 break; |
1141 } | 1142 } |
1142 } | 1143 } |
1143 | 1144 |
1144 // Explicitly mark name as LTR if there is no strong RTL character, | 1145 // Explicitly mark name as LTR if there is no strong RTL character, |
1145 // to avoid the wrong concatenation result similar to "!Yahoo Mail: the | 1146 // to avoid the wrong concatenation result similar to "!Yahoo Mail: the |
1146 // best web-based Email: NIGULP", in which "NIGULP" stands for the Hebrew | 1147 // best web-based Email: NIGULP", in which "NIGULP" stands for the Hebrew |
1147 // or Arabic word for "plugin". | 1148 // or Arabic word for "plugin". |
1148 base::i18n::AdjustStringForLocaleDirection(&title); | 1149 base::i18n::AdjustStringForLocaleDirection(&title); |
1149 | 1150 |
1150 switch (type_) { | 1151 switch (process_type_) { |
1151 case content::PROCESS_TYPE_UTILITY: | 1152 case content::PROCESS_TYPE_UTILITY: |
1152 return l10n_util::GetStringUTF16(IDS_TASK_MANAGER_UTILITY_PREFIX); | 1153 return l10n_util::GetStringUTF16(IDS_TASK_MANAGER_UTILITY_PREFIX); |
1153 | |
1154 case content::PROCESS_TYPE_PROFILE_IMPORT: | |
1155 return l10n_util::GetStringUTF16(IDS_TASK_MANAGER_UTILITY_PREFIX); | |
1156 | |
1157 case content::PROCESS_TYPE_GPU: | 1154 case content::PROCESS_TYPE_GPU: |
1158 return l10n_util::GetStringUTF16(IDS_TASK_MANAGER_GPU_PREFIX); | 1155 return l10n_util::GetStringUTF16(IDS_TASK_MANAGER_GPU_PREFIX); |
1159 | |
1160 case content::PROCESS_TYPE_NACL_BROKER: | |
1161 return l10n_util::GetStringUTF16(IDS_TASK_MANAGER_NACL_BROKER_PREFIX); | |
1162 | |
1163 case content::PROCESS_TYPE_PLUGIN: | 1156 case content::PROCESS_TYPE_PLUGIN: |
1164 case content::PROCESS_TYPE_PPAPI_PLUGIN: | 1157 case content::PROCESS_TYPE_PPAPI_PLUGIN: |
1165 return l10n_util::GetStringFUTF16(IDS_TASK_MANAGER_PLUGIN_PREFIX, title); | 1158 return l10n_util::GetStringFUTF16(IDS_TASK_MANAGER_PLUGIN_PREFIX, title); |
1166 | |
1167 case content::PROCESS_TYPE_PPAPI_BROKER: | 1159 case content::PROCESS_TYPE_PPAPI_BROKER: |
1168 return l10n_util::GetStringFUTF16(IDS_TASK_MANAGER_PLUGIN_BROKER_PREFIX, | 1160 return l10n_util::GetStringFUTF16(IDS_TASK_MANAGER_PLUGIN_BROKER_PREFIX, |
1169 title); | 1161 title); |
1170 | 1162 case PROCESS_TYPE_PROFILE_IMPORT: |
1171 case content::PROCESS_TYPE_NACL_LOADER: | 1163 return l10n_util::GetStringUTF16(IDS_TASK_MANAGER_UTILITY_PREFIX); |
| 1164 case PROCESS_TYPE_NACL_BROKER: |
| 1165 return l10n_util::GetStringUTF16(IDS_TASK_MANAGER_NACL_BROKER_PREFIX); |
| 1166 case PROCESS_TYPE_NACL_LOADER: |
1172 return l10n_util::GetStringFUTF16(IDS_TASK_MANAGER_NACL_PREFIX, title); | 1167 return l10n_util::GetStringFUTF16(IDS_TASK_MANAGER_NACL_PREFIX, title); |
1173 | |
1174 // These types don't need display names or get them from elsewhere. | 1168 // These types don't need display names or get them from elsewhere. |
1175 case content::PROCESS_TYPE_BROWSER: | 1169 case content::PROCESS_TYPE_BROWSER: |
1176 case content::PROCESS_TYPE_RENDERER: | 1170 case content::PROCESS_TYPE_RENDERER: |
1177 case content::PROCESS_TYPE_ZYGOTE: | 1171 case content::PROCESS_TYPE_ZYGOTE: |
1178 case content::PROCESS_TYPE_SANDBOX_HELPER: | 1172 case content::PROCESS_TYPE_SANDBOX_HELPER: |
1179 case content::PROCESS_TYPE_MAX: | 1173 case content::PROCESS_TYPE_MAX: |
1180 NOTREACHED(); | 1174 NOTREACHED(); |
1181 break; | 1175 break; |
1182 | 1176 |
1183 case content::PROCESS_TYPE_WORKER: | 1177 case content::PROCESS_TYPE_WORKER: |
1184 NOTREACHED() << "Workers are not handled by this provider."; | 1178 NOTREACHED() << "Workers are not handled by this provider."; |
1185 break; | 1179 break; |
1186 | |
1187 case content::PROCESS_TYPE_UNKNOWN: | 1180 case content::PROCESS_TYPE_UNKNOWN: |
1188 NOTREACHED() << "Need localized name for child process type."; | 1181 NOTREACHED() << "Need localized name for child process type."; |
1189 } | 1182 } |
1190 | 1183 |
1191 return title; | 1184 return title; |
1192 } | 1185 } |
1193 | 1186 |
1194 //////////////////////////////////////////////////////////////////////////////// | 1187 //////////////////////////////////////////////////////////////////////////////// |
1195 // TaskManagerChildProcessResourceProvider class | 1188 // TaskManagerChildProcessResourceProvider class |
1196 //////////////////////////////////////////////////////////////////////////////// | 1189 //////////////////////////////////////////////////////////////////////////////// |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1241 pid_to_resources_.clear(); | 1234 pid_to_resources_.clear(); |
1242 | 1235 |
1243 BrowserChildProcessObserver::Remove(this); | 1236 BrowserChildProcessObserver::Remove(this); |
1244 } | 1237 } |
1245 | 1238 |
1246 void TaskManagerChildProcessResourceProvider::BrowserChildProcessHostConnected( | 1239 void TaskManagerChildProcessResourceProvider::BrowserChildProcessHostConnected( |
1247 const content::ChildProcessData& data) { | 1240 const content::ChildProcessData& data) { |
1248 DCHECK(updating_); | 1241 DCHECK(updating_); |
1249 | 1242 |
1250 // Workers are handled by TaskManagerWorkerResourceProvider. | 1243 // Workers are handled by TaskManagerWorkerResourceProvider. |
1251 if (data.type == content::PROCESS_TYPE_WORKER) | 1244 if (data.process_type == content::PROCESS_TYPE_WORKER) |
1252 return; | 1245 return; |
1253 if (resources_.count(data.handle)) { | 1246 if (resources_.count(data.handle)) { |
1254 // The case may happen that we have added a child_process_info as part of | 1247 // The case may happen that we have added a child_process_info as part of |
1255 // the iteration performed during StartUpdating() call but the notification | 1248 // the iteration performed during StartUpdating() call but the notification |
1256 // that it has connected was not fired yet. So when the notification | 1249 // that it has connected was not fired yet. So when the notification |
1257 // happens, we already know about this plugin and just ignore it. | 1250 // happens, we already know about this plugin and just ignore it. |
1258 return; | 1251 return; |
1259 } | 1252 } |
1260 AddToTaskManager(data); | 1253 AddToTaskManager(data); |
1261 } | 1254 } |
1262 | 1255 |
1263 void TaskManagerChildProcessResourceProvider:: | 1256 void TaskManagerChildProcessResourceProvider:: |
1264 BrowserChildProcessHostDisconnected(const content::ChildProcessData& data) { | 1257 BrowserChildProcessHostDisconnected(const content::ChildProcessData& data) { |
1265 DCHECK(updating_); | 1258 DCHECK(updating_); |
1266 | 1259 |
1267 if (data.type == content::PROCESS_TYPE_WORKER) | 1260 if (data.process_type == content::PROCESS_TYPE_WORKER) |
1268 return; | 1261 return; |
1269 ChildProcessMap::iterator iter = resources_.find(data.handle); | 1262 ChildProcessMap::iterator iter = resources_.find(data.handle); |
1270 if (iter == resources_.end()) { | 1263 if (iter == resources_.end()) { |
1271 // ChildProcessData disconnection notifications are asynchronous, so we | 1264 // ChildProcessData disconnection notifications are asynchronous, so we |
1272 // might be notified for a plugin we don't know anything about (if it was | 1265 // might be notified for a plugin we don't know anything about (if it was |
1273 // closed before the task manager was shown and destroyed after that). | 1266 // closed before the task manager was shown and destroyed after that). |
1274 return; | 1267 return; |
1275 } | 1268 } |
1276 // Remove the resource from the Task Manager. | 1269 // Remove the resource from the Task Manager. |
1277 TaskManagerChildProcessResource* resource = iter->second; | 1270 TaskManagerChildProcessResource* resource = iter->second; |
1278 task_manager_->RemoveResource(resource); | 1271 task_manager_->RemoveResource(resource); |
1279 // Remove it from the provider. | 1272 // Remove it from the provider. |
1280 resources_.erase(iter); | 1273 resources_.erase(iter); |
1281 // Remove it from our pid map. | 1274 // Remove it from our pid map. |
1282 PidResourceMap::iterator pid_iter = | 1275 PidResourceMap::iterator pid_iter = |
1283 pid_to_resources_.find(resource->process_id()); | 1276 pid_to_resources_.find(resource->process_id()); |
1284 DCHECK(pid_iter != pid_to_resources_.end()); | 1277 DCHECK(pid_iter != pid_to_resources_.end()); |
1285 if (pid_iter != pid_to_resources_.end()) | 1278 if (pid_iter != pid_to_resources_.end()) |
1286 pid_to_resources_.erase(pid_iter); | 1279 pid_to_resources_.erase(pid_iter); |
1287 | 1280 |
1288 // Finally, delete the resource. | 1281 // Finally, delete the resource. |
1289 delete resource; | 1282 delete resource; |
1290 } | 1283 } |
1291 | 1284 |
1292 void TaskManagerChildProcessResourceProvider::AddToTaskManager( | 1285 void TaskManagerChildProcessResourceProvider::AddToTaskManager( |
1293 const content::ChildProcessData& child_process_data) { | 1286 const content::ChildProcessData& child_process_data) { |
1294 TaskManagerChildProcessResource* resource = | 1287 TaskManagerChildProcessResource* resource = |
1295 new TaskManagerChildProcessResource( | 1288 new TaskManagerChildProcessResource( |
1296 child_process_data.type, | 1289 child_process_data.process_type, |
1297 child_process_data.name, | 1290 child_process_data.name, |
1298 child_process_data.handle, | 1291 child_process_data.handle, |
1299 child_process_data.id); | 1292 child_process_data.id); |
1300 resources_[child_process_data.handle] = resource; | 1293 resources_[child_process_data.handle] = resource; |
1301 pid_to_resources_[resource->process_id()] = resource; | 1294 pid_to_resources_[resource->process_id()] = resource; |
1302 task_manager_->AddResource(resource); | 1295 task_manager_->AddResource(resource); |
1303 } | 1296 } |
1304 | 1297 |
1305 // The ChildProcessData::Iterator has to be used from the IO thread. | 1298 // The ChildProcessData::Iterator has to be used from the IO thread. |
1306 void TaskManagerChildProcessResourceProvider::RetrieveChildProcessData() { | 1299 void TaskManagerChildProcessResourceProvider::RetrieveChildProcessData() { |
1307 std::vector<content::ChildProcessData> child_processes; | 1300 std::vector<content::ChildProcessData> child_processes; |
1308 for (BrowserChildProcessHostIterator iter; !iter.Done(); ++iter) { | 1301 for (BrowserChildProcessHostIterator iter; !iter.Done(); ++iter) { |
1309 // Only add processes which are already started, since we need their handle. | 1302 // Only add processes which are already started, since we need their handle. |
1310 if (iter.GetData().handle == base::kNullProcessHandle) | 1303 if (iter.GetData().handle == base::kNullProcessHandle) |
1311 continue; | 1304 continue; |
1312 if (iter.GetData().type == content::PROCESS_TYPE_WORKER) | 1305 if (iter.GetData().process_type == content::PROCESS_TYPE_WORKER) |
1313 continue; | 1306 continue; |
1314 child_processes.push_back(iter.GetData()); | 1307 child_processes.push_back(iter.GetData()); |
1315 } | 1308 } |
1316 // Now notify the UI thread that we have retrieved information about child | 1309 // Now notify the UI thread that we have retrieved information about child |
1317 // processes. | 1310 // processes. |
1318 BrowserThread::PostTask( | 1311 BrowserThread::PostTask( |
1319 BrowserThread::UI, FROM_HERE, | 1312 BrowserThread::UI, FROM_HERE, |
1320 base::Bind( | 1313 base::Bind( |
1321 &TaskManagerChildProcessResourceProvider::ChildProcessDataRetreived, | 1314 &TaskManagerChildProcessResourceProvider::ChildProcessDataRetreived, |
1322 this, child_processes)); | 1315 this, child_processes)); |
(...skipping 580 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1903 case content::NOTIFICATION_WEB_CONTENTS_CONNECTED: | 1896 case content::NOTIFICATION_WEB_CONTENTS_CONNECTED: |
1904 Add(web_contents->GetRenderViewHost()); | 1897 Add(web_contents->GetRenderViewHost()); |
1905 break; | 1898 break; |
1906 case content::NOTIFICATION_WEB_CONTENTS_DISCONNECTED: | 1899 case content::NOTIFICATION_WEB_CONTENTS_DISCONNECTED: |
1907 Remove(web_contents->GetRenderViewHost()); | 1900 Remove(web_contents->GetRenderViewHost()); |
1908 break; | 1901 break; |
1909 default: | 1902 default: |
1910 NOTREACHED() << "Unexpected notification."; | 1903 NOTREACHED() << "Unexpected notification."; |
1911 } | 1904 } |
1912 } | 1905 } |
OLD | NEW |