Index: chrome/browser/extensions/api/developer_private/developer_private_api.cc |
diff --git a/chrome/browser/extensions/api/developer_private/developer_private_api.cc b/chrome/browser/extensions/api/developer_private/developer_private_api.cc |
index 638021dd0781e38cce8ada7b1c26b5ca37ebc19e..3b9a01a11a3de22e0827d1eb8672d1fc26e7ffd1 100644 |
--- a/chrome/browser/extensions/api/developer_private/developer_private_api.cc |
+++ b/chrome/browser/extensions/api/developer_private/developer_private_api.cc |
@@ -10,6 +10,7 @@ |
#include "apps/shell_window.h" |
#include "apps/shell_window_registry.h" |
#include "base/base64.h" |
+#include "base/bind.h" |
#include "base/command_line.h" |
#include "base/file_util.h" |
#include "base/files/file_enumerator.h" |
@@ -35,6 +36,7 @@ |
#include "chrome/browser/sync_file_system/drive_backend_v1/drive_file_sync_service.h" |
#include "chrome/browser/sync_file_system/syncable_file_system_util.h" |
#include "chrome/browser/ui/chrome_select_file_policy.h" |
+#include "chrome/browser/ui/webui/extensions/extension_error_ui_util.h" |
#include "chrome/browser/ui/webui/extensions/extension_icon_source.h" |
#include "chrome/common/extensions/api/developer_private.h" |
#include "chrome/common/extensions/manifest_handlers/app_launch_info.h" |
@@ -48,6 +50,7 @@ |
#include "content/public/browser/site_instance.h" |
#include "content/public/browser/storage_partition.h" |
#include "content/public/browser/web_contents.h" |
+#include "extensions/browser/extension_error.h" |
#include "extensions/browser/extension_registry.h" |
#include "extensions/browser/extension_system.h" |
#include "extensions/browser/management_policy.h" |
@@ -135,6 +138,12 @@ std::string GetExtensionID(const RenderViewHost* render_view_host) { |
return render_view_host->GetSiteInstance()->GetSiteURL().host(); |
} |
+void SetString(base::DictionaryValue* dict, |
+ const std::string& name, |
+ const base::string16& value) { |
+ dict->SetString(name, value); |
+} |
+ |
} // namespace |
namespace AllowFileAccess = api::developer_private::AllowFileAccess; |
@@ -171,10 +180,23 @@ DeveloperPrivateEventRouter::DeveloperPrivateEventRouter(Profile* profile) |
types[i], |
content::Source<Profile>(profile_)); |
} |
+ |
+ ErrorConsole::Get(profile)->AddObserver(this); |
} |
+DeveloperPrivateEventRouter::~DeveloperPrivateEventRouter() { |
+ ErrorConsole::Get(profile_)->RemoveObserver(this); |
+} |
-DeveloperPrivateEventRouter::~DeveloperPrivateEventRouter() {} |
+void DeveloperPrivateEventRouter::AddExtensionId( |
+ const std::string& extension_id) { |
+ extension_ids_.insert(extension_id); |
+} |
+ |
+void DeveloperPrivateEventRouter::RemoveExtensionId( |
+ const std::string& extension_id) { |
+ extension_ids_.erase(extension_id); |
+} |
void DeveloperPrivateEventRouter::Observe( |
int type, |
@@ -232,6 +254,25 @@ void DeveloperPrivateEventRouter::Observe( |
ExtensionSystem::Get(profile)->event_router()->BroadcastEvent(event.Pass()); |
} |
+void DeveloperPrivateEventRouter::OnErrorAdded(const ExtensionError* error) { |
+ // We don't want to handle errors thrown by extensions subscribed to these |
+ // events (currently only the Apps Developer Tool), because doing so risks |
+ // entering a loop. |
+ if (extension_ids_.find(error->extension_id()) != extension_ids_.end()) |
+ return; |
+ |
+ developer::EventData event_data; |
+ event_data.event_type = developer::EVENT_TYPE_ERROR_ADDED; |
+ event_data.item_id = error->extension_id(); |
+ |
+ scoped_ptr<base::ListValue> args(new base::ListValue); |
+ args->Append(event_data.ToValue().release()); |
+ |
+ ExtensionSystem::Get(profile_)->event_router()->BroadcastEvent( |
+ scoped_ptr<Event>(new Event( |
+ developer_private::OnItemStateChanged::kEventName, args.Pass()))); |
+} |
+ |
void DeveloperPrivateAPI::SetLastUnpackedDirectory(const base::FilePath& path) { |
last_unpacked_directory_ = path; |
} |
@@ -247,16 +288,22 @@ void DeveloperPrivateAPI::Shutdown() {} |
void DeveloperPrivateAPI::OnListenerAdded( |
const EventListenerInfo& details) { |
- if (!developer_private_event_router_) |
+ if (!developer_private_event_router_) { |
developer_private_event_router_.reset( |
new DeveloperPrivateEventRouter(profile_)); |
+ } |
+ |
+ developer_private_event_router_->AddExtensionId(details.extension_id); |
} |
void DeveloperPrivateAPI::OnListenerRemoved( |
const EventListenerInfo& details) { |
if (!ExtensionSystem::Get(profile_)->event_router()->HasEventListener( |
- developer_private::OnItemStateChanged::kEventName)) |
+ developer_private::OnItemStateChanged::kEventName)) { |
developer_private_event_router_.reset(NULL); |
+ } else { |
+ developer_private_event_router_->RemoveExtensionId(details.extension_id); |
+ } |
} |
namespace api { |
@@ -272,9 +319,9 @@ bool DeveloperPrivateAutoUpdateFunction::RunImpl() { |
DeveloperPrivateAutoUpdateFunction::~DeveloperPrivateAutoUpdateFunction() {} |
scoped_ptr<developer::ItemInfo> |
- DeveloperPrivateGetItemsInfoFunction::CreateItemInfo( |
- const Extension& item, |
- bool item_is_enabled) { |
+DeveloperPrivateGetItemsInfoFunction::CreateItemInfo( |
+ const Extension& item, |
+ bool item_is_enabled) { |
scoped_ptr<developer::ItemInfo> info(new developer::ItemInfo()); |
ExtensionSystem* system = ExtensionSystem::Get(GetProfile()); |
@@ -308,12 +355,38 @@ scoped_ptr<developer::ItemInfo> |
if (Manifest::IsUnpackedLocation(item.location())) { |
info->path.reset( |
new std::string(base::UTF16ToUTF8(item.path().LossyDisplayName()))); |
- for (std::vector<extensions::InstallWarning>::const_iterator it = |
- item.install_warnings().begin(); |
- it != item.install_warnings().end(); ++it) { |
- developer::InstallWarning* warning = new developer::InstallWarning(); |
- warning->message = it->message; |
- info->install_warnings.push_back(make_linked_ptr(warning)); |
+ // If the ErrorConsole is enabled, get the errors for the extension and add |
+ // them to the list. Otherwise, use the install warnings (using both is |
+ // redundant). |
+ ErrorConsole* error_console = ErrorConsole::Get(GetProfile()); |
+ if (error_console->enabled()) { |
+ const ErrorList& errors = error_console->GetErrorsForExtension(item.id()); |
+ if (!errors.empty()) { |
+ for (ErrorList::const_iterator iter = errors.begin(); |
+ iter != errors.end(); ++iter) { |
+ if ((*iter)->type() == ExtensionError::MANIFEST_ERROR) { |
+ info->manifest_errors.push_back( |
+ make_linked_ptr((*iter)->ToValue().release())); |
+ } else { // runtime error |
+ const RuntimeError* error = static_cast<const RuntimeError*>(*iter); |
+ scoped_ptr<base::DictionaryValue> value = error->ToValue(); |
+ bool can_inspect = |
+ content::RenderViewHost::FromID( |
+ error->render_process_id(), |
+ error->render_view_id()) != NULL; |
+ value->SetBoolean("canInspect", can_inspect); |
+ info->runtime_errors.push_back(make_linked_ptr(value.release())); |
+ } |
+ } |
+ } |
+ } else { |
+ for (std::vector<extensions::InstallWarning>::const_iterator it = |
+ item.install_warnings().begin(); |
+ it != item.install_warnings().end(); ++it) { |
+ developer::InstallWarning* warning = new developer::InstallWarning(); |
Dan Beam
2014/02/11 02:43:49
nit: arguably make this a scoped_ptr and .release(
Devlin
2014/02/11 18:41:16
Done.
|
+ warning->message = it->message; |
+ info->install_warnings.push_back(make_linked_ptr(warning)); |
+ } |
} |
} |
@@ -1316,6 +1389,10 @@ bool DeveloperPrivateGetStringsFunction::RunImpl() { |
IDS_APPS_DEVTOOL_MANAGED_PROFILE_DIALOG_DESCRIPTION); |
dvh
2014/02/10 20:04:04
I think that the strings above are probably deprec
Devlin
2014/02/10 22:59:41
Done.
|
#undef SET_STRING |
+ |
+ error_ui_util::GetLocalizedValues( |
+ base::Bind(&SetString, base::Unretained(dict))); |
dvh
2014/02/10 20:04:04
What is it used for?
--
I went through all the re
Devlin
2014/02/10 22:59:41
Woo! That makes it a little cleaner. Done.
|
+ |
return true; |
} |
@@ -1330,6 +1407,58 @@ DeveloperPrivateIsProfileManagedFunction:: |
~DeveloperPrivateIsProfileManagedFunction() { |
} |
+DeveloperPrivateRequestFileSourceFunction:: |
+DeveloperPrivateRequestFileSourceFunction() {} |
Dan Beam
2014/02/11 02:43:49
nit: indent by 4\s to show it's a continuation
Devlin
2014/02/11 18:41:16
Done in Patch Set 2.
|
+ |
+DeveloperPrivateRequestFileSourceFunction:: |
+~DeveloperPrivateRequestFileSourceFunction() {} |
+ |
+bool DeveloperPrivateRequestFileSourceFunction::RunImpl() { |
+ scoped_ptr<developer::RequestFileSource::Params> params( |
+ developer::RequestFileSource::Params::Create(*args_)); |
+ EXTENSION_FUNCTION_VALIDATE(params.get() != NULL); |
+ |
+ base::DictionaryValue* dict = NULL; |
+ if (!params->dict->GetAsDictionary(&dict)) { |
+ NOTREACHED(); |
+ return false; |
+ } |
+ |
+ AddRef(); // Balanced in LaunchCallback(). |
+ error_ui_util::HandleRequestFileSource( |
+ dict, |
+ GetProfile(), |
+ base::Bind(&DeveloperPrivateRequestFileSourceFunction::LaunchCallback, |
+ base::Unretained(this))); |
+ return true; |
+} |
+ |
+void DeveloperPrivateRequestFileSourceFunction::LaunchCallback( |
+ const base::DictionaryValue& results) { |
+ SetResult(results.DeepCopy()); |
+ SendResponse(true); |
+ Release(); // Balanced in RunImpl(). |
+} |
+ |
+DeveloperPrivateOpenDevToolsFunction::DeveloperPrivateOpenDevToolsFunction() {} |
+DeveloperPrivateOpenDevToolsFunction::~DeveloperPrivateOpenDevToolsFunction() {} |
+ |
+bool DeveloperPrivateOpenDevToolsFunction::RunImpl() { |
+ scoped_ptr<developer::OpenDevTools::Params> params( |
+ developer::OpenDevTools::Params::Create(*args_)); |
+ EXTENSION_FUNCTION_VALIDATE(params.get() != NULL); |
+ |
+ base::DictionaryValue* dict = NULL; |
+ if (!params->dict->GetAsDictionary(&dict)) { |
+ NOTREACHED(); |
+ return false; |
+ } |
+ |
+ error_ui_util::HandleOpenDevTools(dict); |
+ |
+ return true; |
+} |
+ |
} // namespace api |
} // namespace extensions |