Add content script activity to the extension activity log.
BUG=39802
Review URL: https://chromiumcodereview.appspot.com/10905245
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@159040 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd
index 1604b46..f095c58 100644
--- a/chrome/app/generated_resources.grd
+++ b/chrome/app/generated_resources.grd
@@ -5278,6 +5278,9 @@
<message name="IDS_EXTENSION_ACTIVITY_API_BLOCK" desc="Text for the label next to an activity message that represents a blocked call to the extension API.">
Blocked API Call
</message>
+ <message name="IDS_EXTENSION_ACTIVITY_CONTENT_SCRIPT" desc="Text for the label next to an activity message that represents a content script injection.">
+ Content Script
+ </message>
<!-- chrome://extension-info bubble -->
<message name="IDS_EXTENSION_SCRIPT_POPUP_IS_RUNNING" desc="The label in the extension info bubble that indicates the extension is running scripts on this page">
diff --git a/chrome/browser/extensions/activity_log.cc b/chrome/browser/extensions/activity_log.cc
index 937ee84e4..877db44 100644
--- a/chrome/browser/extensions/activity_log.cc
+++ b/chrome/browser/extensions/activity_log.cc
@@ -6,8 +6,14 @@
#include "base/command_line.h"
#include "base/logging.h"
+#include "base/string_util.h"
+#include "chrome/browser/extensions/extension_service.h"
+#include "chrome/browser/extensions/extension_system.h"
+#include "chrome/browser/profiles/profile.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/extensions/extension.h"
+#include "content/public/browser/web_contents.h"
+#include "googleurl/src/gurl.h"
namespace extensions {
@@ -55,17 +61,52 @@
void ActivityLog::Log(const Extension* extension,
Activity activity,
- const std::string& msg) const {
+ const std::string& message) const {
+ std::vector<std::string> messages(1, message);
+ Log(extension, activity, messages);
+}
+
+void ActivityLog::Log(const Extension* extension,
+ Activity activity,
+ const std::vector<std::string>& messages) const {
base::AutoLock scoped_lock(lock_);
ObserverMap::const_iterator iter = observers_.find(extension);
if (iter != observers_.end()) {
iter->second->Notify(&Observer::OnExtensionActivity, extension, activity,
- msg);
+ messages);
}
if (log_activity_to_stdout_) {
- LOG(INFO) << extension->id() + ":" + ActivityToString(activity) + ":" + msg;
+ LOG(INFO) << extension->id() << ":" << ActivityToString(activity) << ":" <<
+ JoinString(messages, ' ');
+ }
+}
+
+void ActivityLog::OnContentScriptsExecuting(
+ const content::WebContents* web_contents,
+ const ExecutingScriptsMap& extension_ids,
+ int32 on_page_id,
+ const GURL& on_url) {
+ Profile* profile =
+ Profile::FromBrowserContext(web_contents->GetBrowserContext());
+ const ExtensionService* extension_service =
+ ExtensionSystem::Get(profile)->extension_service();
+ const ExtensionSet* extensions = extension_service->extensions();
+
+ for (ExecutingScriptsMap::const_iterator it = extension_ids.begin();
+ it != extension_ids.end(); ++it) {
+ const Extension* extension = extensions->GetByID(it->first);
+ if (!extension || !HasObservers(extension))
+ continue;
+
+ for (std::set<std::string>::const_iterator it2 = it->second.begin();
+ it2 != it->second.end(); ++it2) {
+ std::vector<std::string> messages;
+ messages.push_back(on_url.spec());
+ messages.push_back(*it2);
+ Log(extension, ActivityLog::ACTIVITY_CONTENT_SCRIPT, messages);
+ }
}
}
@@ -76,6 +117,8 @@
return "api_call";
case ActivityLog::ACTIVITY_EXTENSION_API_BLOCK:
return "api_block";
+ case ActivityLog::ACTIVITY_CONTENT_SCRIPT:
+ return "content_script";
default:
NOTREACHED();
return "";
diff --git a/chrome/browser/extensions/activity_log.h b/chrome/browser/extensions/activity_log.h
index d9c459a..f24000d9 100644
--- a/chrome/browser/extensions/activity_log.h
+++ b/chrome/browser/extensions/activity_log.h
@@ -7,31 +7,35 @@
#include <map>
#include <string>
+#include <vector>
#include "base/memory/singleton.h"
#include "base/observer_list_threadsafe.h"
#include "base/synchronization/lock.h"
+#include "chrome/browser/extensions/tab_helper.h"
namespace extensions {
class Extension;
// A utility for tracing interesting activity for each extension.
-class ActivityLog {
+class ActivityLog : public TabHelper::ContentScriptObserver {
public:
enum Activity {
- ACTIVITY_EXTENSION_API_CALL, // Extension API invocation is called.
- ACTIVITY_EXTENSION_API_BLOCK // Extension API invocation is blocked.
+ ACTIVITY_EXTENSION_API_CALL, // Extension API invocation is called.
+ ACTIVITY_EXTENSION_API_BLOCK, // Extension API invocation is blocked.
+ ACTIVITY_CONTENT_SCRIPT // Content script is executing.
};
// Observers can listen for activity events.
class Observer {
public:
- virtual void OnExtensionActivity(const Extension* extension,
- Activity activity,
- const std::string& msg) = 0;
+ virtual void OnExtensionActivity(
+ const Extension* extension,
+ Activity activity,
+ const std::vector<std::string>& messages) = 0;
};
- ~ActivityLog();
+ virtual ~ActivityLog();
static ActivityLog* GetInstance();
// Add/remove observer.
@@ -45,12 +49,22 @@
// Log |activity| for |extension|.
void Log(const Extension* extension,
Activity activity,
- const std::string& msg) const;
+ const std::string& message) const;
+ void Log(const Extension* extension,
+ Activity activity,
+ const std::vector<std::string>& messages) const;
private:
ActivityLog();
friend struct DefaultSingletonTraits<ActivityLog>;
+ // TabHelper::ContentScriptObserver implementation.
+ virtual void OnContentScriptsExecuting(
+ const content::WebContents* web_contents,
+ const ExecutingScriptsMap& extension_ids,
+ int32 page_id,
+ const GURL& on_url) OVERRIDE;
+
static const char* ActivityToString(Activity activity);
// A lock used to synchronize access to member variables.
diff --git a/chrome/browser/extensions/script_badge_controller.cc b/chrome/browser/extensions/script_badge_controller.cc
index ff18157..427e1191b 100644
--- a/chrome/browser/extensions/script_badge_controller.cc
+++ b/chrome/browser/extensions/script_badge_controller.cc
@@ -30,8 +30,10 @@
namespace extensions {
ScriptBadgeController::ScriptBadgeController(content::WebContents* web_contents,
- ScriptExecutor* script_executor)
+ ScriptExecutor* script_executor,
+ TabHelper* tab_helper)
: ScriptExecutor::Observer(script_executor),
+ TabHelper::ContentScriptObserver(tab_helper),
content::WebContentsObserver(web_contents) {
Profile* profile =
Profile::FromBrowserContext(web_contents->GetBrowserContext());
@@ -136,6 +138,48 @@
}
}
+namespace {
+std::string JoinExtensionIDs(const ExecutingScriptsMap& ids) {
+ std::vector<std::string> as_vector;
+ for (ExecutingScriptsMap::const_iterator iter = ids.begin();
+ iter != ids.end(); ++iter) {
+ as_vector.push_back(iter->first);
+ }
+ return "[" + JoinString(as_vector, ',') + "]";
+}
+} // namespace
+
+void ScriptBadgeController::OnContentScriptsExecuting(
+ const content::WebContents* web_contents,
+ const ExecutingScriptsMap& extension_ids,
+ int32 on_page_id,
+ const GURL& on_url) {
+ int32 current_page_id = GetPageID();
+ if (on_page_id != current_page_id)
+ return;
+
+ if (current_page_id < 0) {
+ // Tracking down http://crbug.com/138323.
+ std::string message = base::StringPrintf(
+ "Expected a page ID of %d but there was no navigation entry. "
+ "Extension IDs are %s.",
+ on_page_id,
+ JoinExtensionIDs(extension_ids).c_str());
+ char buf[1024];
+ base::snprintf(buf, arraysize(buf), "%s", message.c_str());
+ LOG(ERROR) << message;
+ return;
+ }
+
+ bool changed = false;
+ for (ExecutingScriptsMap::const_iterator it = extension_ids.begin();
+ it != extension_ids.end(); ++it) {
+ changed |= MarkExtensionExecuting(it->first);
+ }
+ if (changed)
+ NotifyChange();
+}
+
ExtensionService* ScriptBadgeController::GetExtensionService() {
TabContents* tab_contents = TabContents::FromWebContents(web_contents());
return extensions::ExtensionSystem::Get(
@@ -176,53 +220,6 @@
NotifyChange();
}
-bool ScriptBadgeController::OnMessageReceived(const IPC::Message& message) {
- bool handled = true;
- IPC_BEGIN_MESSAGE_MAP(ScriptBadgeController, message)
- IPC_MESSAGE_HANDLER(ExtensionHostMsg_ContentScriptsExecuting,
- OnContentScriptsExecuting)
- IPC_MESSAGE_UNHANDLED(handled = false)
- IPC_END_MESSAGE_MAP()
- return handled;
-}
-
-namespace {
-std::string JoinExtensionIDs(const std::set<std::string>& ids) {
- std::vector<std::string> as_vector(ids.begin(), ids.end());
- return "[" + JoinString(as_vector, ',') + "]";
-}
-} // namespace
-
-void ScriptBadgeController::OnContentScriptsExecuting(
- const std::set<std::string>& extension_ids,
- int32 on_page_id,
- const GURL& on_url) {
- int32 current_page_id = GetPageID();
- if (on_page_id != current_page_id)
- return;
-
- if (current_page_id < 0) {
- // Tracking down http://crbug.com/138323.
- std::string message = base::StringPrintf(
- "Expected a page ID of %d but there was no navigation entry. "
- "Extension IDs are %s.",
- on_page_id,
- JoinExtensionIDs(extension_ids).c_str());
- char buf[1024];
- base::snprintf(buf, arraysize(buf), "%s", message.c_str());
- LOG(ERROR) << message;
- return;
- }
-
- bool changed = false;
- for (std::set<std::string>::const_iterator it = extension_ids.begin();
- it != extension_ids.end(); ++it) {
- changed |= MarkExtensionExecuting(*it);
- }
- if (changed)
- NotifyChange();
-}
-
ExtensionAction* ScriptBadgeController::AddExtensionToCurrentActions(
const std::string& extension_id) {
if (!extensions_in_current_actions_.insert(extension_id).second)
diff --git a/chrome/browser/extensions/script_badge_controller.h b/chrome/browser/extensions/script_badge_controller.h
index 13281fe..ec31f22 100644
--- a/chrome/browser/extensions/script_badge_controller.h
+++ b/chrome/browser/extensions/script_badge_controller.h
@@ -14,6 +14,7 @@
#include "base/memory/ref_counted.h"
#include "chrome/browser/extensions/location_bar_controller.h"
#include "chrome/browser/extensions/script_executor.h"
+#include "chrome/browser/extensions/tab_helper.h"
#include "content/public/browser/notification_observer.h"
#include "content/public/browser/notification_registrar.h"
#include "content/public/browser/web_contents_observer.h"
@@ -49,11 +50,13 @@
class ScriptBadgeController
: public LocationBarController,
public ScriptExecutor::Observer,
+ public TabHelper::ContentScriptObserver,
public content::WebContentsObserver,
public content::NotificationObserver {
public:
explicit ScriptBadgeController(content::WebContents* web_contents,
- ScriptExecutor* script_executor);
+ ScriptExecutor* script_executor,
+ TabHelper* tab_helper);
virtual ~ScriptBadgeController();
// LocationBarController implementation.
@@ -71,6 +74,13 @@
const GURL& on_url,
const base::ListValue& script_result) OVERRIDE;
+ // TabHelper::ContentScriptObserver implementation.
+ virtual void OnContentScriptsExecuting(
+ const content::WebContents* web_contents,
+ const ExecutingScriptsMap& extension_ids,
+ int32 on_page_id,
+ const GURL& on_url) OVERRIDE;
+
private:
// Gets the ExtensionService for |tab_contents_|.
ExtensionService* GetExtensionService();
@@ -82,18 +92,12 @@
virtual void DidNavigateMainFrame(
const content::LoadCommittedDetails& details,
const content::FrameNavigateParams& params) OVERRIDE;
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
// content::NotificationObserver implementation.
virtual void Observe(int type,
const content::NotificationSource& source,
const content::NotificationDetails& details) OVERRIDE;
- // IPC::Message handlers.
- void OnContentScriptsExecuting(const std::set<std::string>& extension_ids,
- int32 page_id,
- const GURL& on_url);
-
// Adds the extension's icon to the list of script badges. Returns
// the script badge ExtensionAction that was added, or NULL if
// extension_id isn't valid.
diff --git a/chrome/browser/extensions/script_badge_controller_unittest.cc b/chrome/browser/extensions/script_badge_controller_unittest.cc
index 760d104f..0be5411 100644
--- a/chrome/browser/extensions/script_badge_controller_unittest.cc
+++ b/chrome/browser/extensions/script_badge_controller_unittest.cc
@@ -15,6 +15,7 @@
#include "chrome/browser/ui/tab_contents/tab_contents.h"
#include "chrome/browser/ui/tab_contents/test_tab_contents.h"
#include "chrome/common/chrome_notification_types.h"
+#include "chrome/common/chrome_switches.h"
#include "chrome/common/chrome_version_info.h"
#include "chrome/common/extensions/extension.h"
#include "chrome/common/extensions/extension_builder.h"
@@ -41,6 +42,16 @@
file_thread_(BrowserThread::FILE, MessageLoop::current()),
current_channel_(chrome::VersionInfo::CHANNEL_DEV) {}
+ static void SetUpTestCase() {
+ old_command_line_ = *CommandLine::ForCurrentProcess();
+ CommandLine::ForCurrentProcess()->AppendSwitch(
+ switches::kEnableScriptBadges);
+ }
+
+ static void TearDownTestCase() {
+ *CommandLine::ForCurrentProcess() = old_command_line_;
+ }
+
virtual void SetUp() OVERRIDE {
// Note that this sets a PageActionController into the
// extensions::TabHelper's location_bar_controller field. Do
@@ -57,9 +68,9 @@
extension_service_ = extension_system->CreateExtensionService(
&command_line, FilePath(), false);
- script_executor_.reset(new ScriptExecutor(web_contents()));
- script_badge_controller_.reset(new ScriptBadgeController(
- web_contents(), script_executor_.get()));
+ TabHelper::CreateForWebContents(web_contents());
+ script_badge_controller_ = static_cast<ScriptBadgeController*>(
+ TabHelper::FromWebContents(web_contents())->location_bar_controller());
}
protected:
@@ -80,15 +91,18 @@
}
ExtensionService* extension_service_;
- scoped_ptr<ScriptExecutor> script_executor_;
- scoped_ptr<ScriptBadgeController> script_badge_controller_;
+ ScriptBadgeController* script_badge_controller_;
private:
+ static CommandLine old_command_line_;
content::TestBrowserThread ui_thread_;
content::TestBrowserThread file_thread_;
Feature::ScopedCurrentChannel current_channel_;
};
+CommandLine ScriptBadgeControllerTest::old_command_line_(
+ CommandLine::NO_PROGRAM);
+
struct CountingNotificationObserver : public content::NotificationObserver {
CountingNotificationObserver() : events(0) {}
diff --git a/chrome/browser/extensions/tab_helper.cc b/chrome/browser/extensions/tab_helper.cc
index e43379a..4c5521f1 100644
--- a/chrome/browser/extensions/tab_helper.cc
+++ b/chrome/browser/extensions/tab_helper.cc
@@ -4,6 +4,7 @@
#include "chrome/browser/extensions/tab_helper.h"
+#include "chrome/browser/extensions/activity_log.h"
#include "chrome/browser/extensions/app_notify_channel_ui.h"
#include "chrome/browser/extensions/crx_installer.h"
#include "chrome/browser/extensions/extension_service.h"
@@ -54,6 +55,19 @@
int TabHelper::kUserDataKey;
+TabHelper::ContentScriptObserver::ContentScriptObserver(TabHelper* tab_helper)
+ : tab_helper_(tab_helper) {
+ tab_helper_->AddContentScriptObserver(this);
+}
+
+TabHelper::ContentScriptObserver::ContentScriptObserver() : tab_helper_(NULL) {
+}
+
+TabHelper::ContentScriptObserver::~ContentScriptObserver() {
+ if (tab_helper_)
+ tab_helper_->RemoveContentScriptObserver(this);
+}
+
TabHelper::TabHelper(content::WebContents* web_contents)
: content::WebContentsObserver(web_contents),
extension_app_(NULL),
@@ -72,18 +86,24 @@
Profile::FromBrowserContext(web_contents->GetBrowserContext())));
if (switch_utils::AreScriptBadgesEnabled()) {
location_bar_controller_.reset(
- new ScriptBadgeController(web_contents, &script_executor_));
+ new ScriptBadgeController(web_contents, &script_executor_, this));
} else {
location_bar_controller_.reset(
new PageActionController(web_contents));
}
+
+ // If more classes need to listen to global content script activity, then
+ // a separate routing class with an observer interface should be written.
+ AddContentScriptObserver(ActivityLog::GetInstance());
+
registrar_.Add(this,
content::NOTIFICATION_LOAD_STOP,
content::Source<NavigationController>(
- &web_contents->GetController()));
+ &web_contents->GetController()));
}
TabHelper::~TabHelper() {
+ RemoveContentScriptObserver(ActivityLog::GetInstance());
}
void TabHelper::CreateApplicationShortcuts() {
@@ -185,6 +205,8 @@
IPC_MESSAGE_HANDLER(ExtensionHostMsg_GetAppInstallState,
OnGetAppInstallState);
IPC_MESSAGE_HANDLER(ExtensionHostMsg_Request, OnRequest)
+ IPC_MESSAGE_HANDLER(ExtensionHostMsg_ContentScriptsExecuting,
+ OnContentScriptsExecuting)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
return handled;
@@ -367,6 +389,17 @@
web_contents()->GetRenderViewHost());
}
+void TabHelper::OnContentScriptsExecuting(
+ const ContentScriptObserver::ExecutingScriptsMap& executing_scripts_map,
+ int32 on_page_id,
+ const GURL& on_url) {
+ FOR_EACH_OBSERVER(ContentScriptObserver, content_script_observers_,
+ OnContentScriptsExecuting(web_contents(),
+ executing_scripts_map,
+ on_page_id,
+ on_url));
+}
+
const Extension* TabHelper::GetExtension(const std::string& extension_app_id) {
if (extension_app_id.empty())
return NULL;
diff --git a/chrome/browser/extensions/tab_helper.h b/chrome/browser/extensions/tab_helper.h
index 01800ad..9540029 100644
--- a/chrome/browser/extensions/tab_helper.h
+++ b/chrome/browser/extensions/tab_helper.h
@@ -31,7 +31,6 @@
class Extension;
class LocationBarController;
class ScriptBadgeController;
-class ScriptExecutor;
// Per-tab extension helper. Also handles non-extension apps.
class TabHelper : public content::WebContentsObserver,
@@ -50,8 +49,41 @@
UPDATE_SHORTCUT // Update icon for app shortcut.
};
+ // Observer base class for classes listening for content script messages
+ // from the renderer.
+ class ContentScriptObserver {
+ public:
+ // Map of extensions IDs to the executing script paths.
+ typedef std::map<std::string, std::set<std::string> > ExecutingScriptsMap;
+
+ // Automatically observes and unobserves |tab_helper| on construction
+ // and destruction. |tab_helper| must outlive |this|.
+ explicit ContentScriptObserver(TabHelper* tab_helper);
+ ContentScriptObserver();
+
+ virtual void OnContentScriptsExecuting(
+ const content::WebContents* web_contents,
+ const ExecutingScriptsMap& executing_scripts_map,
+ int32 on_page_id,
+ const GURL& on_url) = 0;
+
+ protected:
+ virtual ~ContentScriptObserver();
+
+ private:
+ TabHelper* tab_helper_;
+ };
+
virtual ~TabHelper();
+ void AddContentScriptObserver(ContentScriptObserver* observer) {
+ content_script_observers_.AddObserver(observer);
+ }
+
+ void RemoveContentScriptObserver(ContentScriptObserver* observer) {
+ content_script_observers_.RemoveObserver(observer);
+ }
+
void CreateApplicationShortcuts();
bool CanCreateApplicationShortcuts() const;
@@ -147,6 +179,10 @@
int return_route_id,
int callback_id);
void OnRequest(const ExtensionHostMsg_Request_Params& params);
+ void OnContentScriptsExecuting(
+ const ContentScriptObserver::ExecutingScriptsMap& extension_ids,
+ int32 page_id,
+ const GURL& on_url);
// App extensions related methods:
@@ -186,9 +222,9 @@
// Data for app extensions ---------------------------------------------------
- // Our observers. Declare at top so that it will outlive all other members,
- // since they might add themselves as observers.
- ObserverList<Observer> observers_;
+ // Our content script observers. Declare at top so that it will outlive all
+ // other members, since they might add themselves as observers.
+ ObserverList<ContentScriptObserver> content_script_observers_;
// If non-null this tab is an app tab and this is the extension the tab was
// created for.
diff --git a/chrome/browser/resources/extensions/extension_activity.css b/chrome/browser/resources/extensions/extension_activity.css
index 54ab2f0..fb40cdf4 100644
--- a/chrome/browser/resources/extensions/extension_activity.css
+++ b/chrome/browser/resources/extensions/extension_activity.css
@@ -11,6 +11,7 @@
}
.extension-activity-time,
-.extension-activity-label {
+.extension-activity-label,
+.extension-activity-message {
-webkit-padding-end: 10px;
}
diff --git a/chrome/browser/resources/extensions/extension_activity.html b/chrome/browser/resources/extensions/extension_activity.html
index 411cc69..5a659f4 100644
--- a/chrome/browser/resources/extensions/extension_activity.html
+++ b/chrome/browser/resources/extensions/extension_activity.html
@@ -41,6 +41,8 @@
i18n-content="extensionActivityApiCall"></span>
<span class="extension-activity-label-1"
i18n-content="extensionActivityApiBlock"></span>
+ <span class="extension-activity-label-2"
+ i18n-content="extensionActivityContentScript"></span>
</div>
<div class="extension-activity-item">
diff --git a/chrome/browser/resources/extensions/extension_activity.js b/chrome/browser/resources/extensions/extension_activity.js
index e4eb85c..b0f8866b 100644
--- a/chrome/browser/resources/extensions/extension_activity.js
+++ b/chrome/browser/resources/extensions/extension_activity.js
@@ -25,6 +25,7 @@
function handleExtensionActivity(result) {
var template = $('template-collection');
+ // Clone the activity item template.
var item =
template.querySelector('.extension-activity-item').cloneNode(true);
item.querySelector('.extension-activity-time').textContent =
@@ -32,8 +33,15 @@
item.querySelector('.extension-activity-label').textContent =
template.querySelector('.extension-activity-label-' + result.activity)
.textContent;
- item.querySelector('.extension-activity-message').textContent =
- result.message;
+
+ // Clone the message node and then delete the empty template.
+ var msgNode = item.querySelector('.extension-activity-message');
+ for (var i = 0; i < result.messages.length; ++i) {
+ var newNode = msgNode.cloneNode(true);
+ newNode.textContent = result.messages[i];
+ item.appendChild(newNode);
+ }
+ item.removeChild(msgNode);
$('extension-activity-list').appendChild(item);
}
diff --git a/chrome/browser/ui/webui/extensions/extension_activity_ui.cc b/chrome/browser/ui/webui/extensions/extension_activity_ui.cc
index 93dd8227..589a29d 100644
--- a/chrome/browser/ui/webui/extensions/extension_activity_ui.cc
+++ b/chrome/browser/ui/webui/extensions/extension_activity_ui.cc
@@ -33,6 +33,8 @@
IDS_EXTENSION_ACTIVITY_API_CALL);
source->AddLocalizedString("extensionActivityApiBlock",
IDS_EXTENSION_ACTIVITY_API_BLOCK);
+ source->AddLocalizedString("extensionActivityContentScript",
+ IDS_EXTENSION_ACTIVITY_CONTENT_SCRIPT);
source->set_use_json_js_format_v2();
source->set_json_path("strings.js");
@@ -94,10 +96,14 @@
void ExtensionActivityUI::OnExtensionActivity(
const extensions::Extension* extension,
extensions::ActivityLog::Activity activity,
- const std::string& msg) {
+ const std::vector<std::string>& messages) {
+ scoped_ptr<ListValue> messages_list(new ListValue());
+ messages_list->AppendStrings(messages);
+
DictionaryValue result;
result.SetInteger("activity", activity);
- result.SetString("message", msg);
+ result.Set("messages", messages_list.release());
+
web_ui()->CallJavascriptFunction("extension_activity.handleExtensionActivity",
result);
}
diff --git a/chrome/browser/ui/webui/extensions/extension_activity_ui.h b/chrome/browser/ui/webui/extensions/extension_activity_ui.h
index a86cec8..f77ea424 100644
--- a/chrome/browser/ui/webui/extensions/extension_activity_ui.h
+++ b/chrome/browser/ui/webui/extensions/extension_activity_ui.h
@@ -22,9 +22,10 @@
void HandleRequestExtensionData(const base::ListValue* args);
// ActivityLog::Observer implementation.
- virtual void OnExtensionActivity(const extensions::Extension* extension,
- extensions::ActivityLog::Activity activity,
- const std::string& msg) OVERRIDE;
+ virtual void OnExtensionActivity(
+ const extensions::Extension* extension,
+ extensions::ActivityLog::Activity activity,
+ const std::vector<std::string>& messages) OVERRIDE;
private:
const extensions::Extension* extension_;
diff --git a/chrome/common/extensions/extension_messages.h b/chrome/common/extensions/extension_messages.h
index 9bed176..444c423 100644
--- a/chrome/common/extensions/extension_messages.h
+++ b/chrome/common/extensions/extension_messages.h
@@ -115,6 +115,9 @@
// Substitution map for l10n messages.
typedef std::map<std::string, std::string> SubstitutionMap;
+// Map of extensions IDs to the executing script paths.
+typedef std::map<std::string, std::set<std::string> > ExecutingScriptsMap;
+
struct ExtensionMsg_Loaded_Params {
ExtensionMsg_Loaded_Params();
~ExtensionMsg_Loaded_Params();
@@ -499,7 +502,7 @@
// frame (e.g. if executing in an iframe this is the page ID of the parent,
// unless the parent is an iframe... etc).
IPC_MESSAGE_ROUTED3(ExtensionHostMsg_ContentScriptsExecuting,
- std::set<std::string> /* extensions that have scripts */,
+ ExecutingScriptsMap,
int32 /* page_id of the _topmost_ frame */,
GURL /* url of the _topmost_ frame */)
diff --git a/chrome/renderer/extensions/user_script_slave.cc b/chrome/renderer/extensions/user_script_slave.cc
index c807516..7507ed1 100644
--- a/chrome/renderer/extensions/user_script_slave.cc
+++ b/chrome/renderer/extensions/user_script_slave.cc
@@ -262,7 +262,7 @@
int num_css = 0;
int num_scripts = 0;
- std::set<std::string> extensions_executing_scripts;
+ ExecutingScriptsMap extensions_executing_scripts;
for (size_t i = 0; i < scripts_.size(); ++i) {
std::vector<WebScriptSource> sources;
@@ -332,7 +332,11 @@
EXTENSION_GROUP_CONTENT_SCRIPTS);
UMA_HISTOGRAM_TIMES("Extensions.InjectScriptTime", exec_timer.Elapsed());
- extensions_executing_scripts.insert(extension->id());
+ for (std::vector<WebScriptSource>::const_iterator iter = sources.begin();
+ iter != sources.end(); ++iter) {
+ extensions_executing_scripts[extension->id()].insert(
+ GURL(iter->url).path());
+ }
}
}