diff options
18 files changed, 322 insertions, 1 deletions
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd index ef7dafb..1c17dd7 100644 --- a/chrome/app/generated_resources.grd +++ b/chrome/app/generated_resources.grd @@ -4260,6 +4260,9 @@ Update checks have repeatedly failed for the extension "<ph name="EXTENSION_NAME <message name="IDS_EXTENSIONS_OPTIONS_LINK" desc="The button text for the options button."> Options </message> + <message name="IDS_EXTENSIONS_ACTIVITY_LINK" desc="The link for showing extension activity."> + Activity + </message> <message name="IDS_EXTENSIONS_SHOW_BUTTON" desc="The text for the Show link."> Show button </message> @@ -4386,6 +4389,17 @@ Keep your key file in a safe place. You will need it to create new versions of y Hide Details </message> + <!-- chrome://extension-activity page --> + <message name="IDS_EXTENSION_ACTIVITY_TITLE" desc="Title for the extension-activity tab."> + Extension Activity + </message> + <message name="IDS_EXTENSION_ACTIVITY_API_CALL" desc="Text for the label next to an activity message that represents a call to the extension API."> + API Call + </message> + <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> + <!-- Global error messages for extensions --> <message name="IDS_EXTENSION_WARNINGS_WRENCH_MENU_ITEM" desc="The wrench menu item indicating that extensions caused problems"> Misbehaving extension @@ -5111,6 +5125,12 @@ Keep your key file in a safe place. You will need it to create new versions of y <message name="IDS_FLAGS_SHADOW_DOM_DESCRIPTION" desc="Description for the flag to enable Shadow DOM."> This API allows web applications to use Web Components. </message> + <message name="IDS_FLAGS_ENABLE_EXTENSION_ACTIVITY_UI_NAME" desc="Name for the flag to enable the extension activity UI."> + Enable extension activity UI + </message> + <message name="IDS_FLAGS_ENABLE_EXTENSION_ACTIVITY_UI_DESCRIPTION" desc="Description for the flag to enable the extension activity UI."> + Enable experimental UI that shows a log of extension activity. + </message> <!-- Crashes --> <message name="IDS_CRASHES_TITLE" desc="Title for the chrome://crashes page."> Crashes diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc index 8e51c38..89f5aca 100644 --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc @@ -562,6 +562,13 @@ const Experiment kExperiments[] = { kOsAll, SINGLE_VALUE_TYPE(switches::kEnableShadowDOM) }, + { + "enable-extension-activity-ui", + IDS_FLAGS_ENABLE_EXTENSION_ACTIVITY_UI_NAME, + IDS_FLAGS_ENABLE_EXTENSION_ACTIVITY_UI_DESCRIPTION, + kOsAll, + SINGLE_VALUE_TYPE(switches::kEnableExtensionActivityUI) + } }; const Experiment* experiments = kExperiments; diff --git a/chrome/browser/browser_resources.grd b/chrome/browser/browser_resources.grd index 0cf1899..66826cd 100644 --- a/chrome/browser/browser_resources.grd +++ b/chrome/browser/browser_resources.grd @@ -55,6 +55,8 @@ <include name="IDR_EXTENSIONS_INFOBAR_CSS" file="resources\extensions_infobar.css" flattenhtml="true" type="BINDATA" /> </if> <include name="IDR_EXTENSION_LIST_JS" file="resources\extensions\extension_list.js" flattenhtml="true" type="BINDATA" /> + <include name="IDR_EXTENSION_ACTIVITY_HTML" file="resources\extensions\extension_activity.html" flattenhtml="true" type="BINDATA" /> + <include name="IDR_EXTENSION_ACTIVITY_JS" file="resources\extensions\extension_activity.js" flattenhtml="true" type="BINDATA" /> <include name="IDR_EXTENSIONS_HTML" file="resources\extensions\extensions.html" flattenhtml="true" type="BINDATA" /> <include name="IDR_EXTENSIONS_JS" file="resources\extensions\extensions.js" flattenhtml="true" type="BINDATA" /> <include name="IDR_FLAGS_HTML" file="resources\flags.html" flattenhtml="true" type="BINDATA" /> diff --git a/chrome/browser/resources/extensions/extension_activity.css b/chrome/browser/resources/extensions/extension_activity.css new file mode 100644 index 0000000..54ab2f0 --- /dev/null +++ b/chrome/browser/resources/extensions/extension_activity.css @@ -0,0 +1,16 @@ +/* Copyright (c) 2012 The Chromium Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. */ + +body { + -webkit-padding-start: 0.67em; +} + +#extension-activity-list { + -webkit-padding-before: 0.67em; +} + +.extension-activity-time, +.extension-activity-label { + -webkit-padding-end: 10px; +} diff --git a/chrome/browser/resources/extensions/extension_activity.html b/chrome/browser/resources/extensions/extension_activity.html new file mode 100644 index 0000000..286b814 --- /dev/null +++ b/chrome/browser/resources/extensions/extension_activity.html @@ -0,0 +1,53 @@ +<!DOCTYPE html> +<html i18n-values="dir:textdirection;"> +<head> +<meta charset="utf-8"> + +<link rel="stylesheet" href="extensions.css"> +<link rel="stylesheet" href="extension_activity.css"> +<link rel="stylesheet" href="../shared/css/chrome_shared2.css"> + +<script src="chrome://resources/js/cr.js"></script> +<script src="chrome://resources/js/i18n_template.js"></script> +<script src="chrome://resources/js/util.js"></script> + +<script src="chrome://extension-activity/strings.js"></script> +<script src="chrome://extension-activity/extension_activity.js"></script> + +</head> + +<body> + +<div id="extension-activity"> + <h1 i18n-content="extensionActivity"></h1> + <div class="extension-list-item"> + <div class="extension-details"> + <div> + <span class="extension-title"></span> + <span class="extension-version"></span> + </div> + <p class="extension-description"></p> + </div> + </div> + <div id="extension-activity-list"></div> +</div> + +<div id="template-collection" hidden> + <div class="extension-activity-labels"> + <!-- The indices here match the activity enum defined in + chrome/browser/extensions/extension_activity_log.h --> + <span class="extension-activity-label-0" + i18n-content="extensionActivityApiCall"></span> + <span class="extension-activity-label-1" + i18n-content="extensionActivityApiBlock"></span> + </div> + + <div class="extension-activity-item"> + <span class="extension-activity-time"></span> + <span class="extension-activity-label"></span> + <span class="extension-activity-message"></span> + </div> +</div> + +</body> +</html> diff --git a/chrome/browser/resources/extensions/extension_activity.js b/chrome/browser/resources/extensions/extension_activity.js new file mode 100644 index 0000000..c384660f --- /dev/null +++ b/chrome/browser/resources/extensions/extension_activity.js @@ -0,0 +1,50 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +cr.define('extension_activity', function() { + 'use strict'; + + function initialize() { + i18nTemplate.process(document, templateData); + + var params = parseQueryParams(location); + if (params.extensionId) + chrome.send('requestExtensionData', [params.extensionId]); + } + + function handleExtensionData(result) { + var extension = result.extension; + + var item = document.querySelector('.extension-list-item'); + item.style.backgroundImage = 'url(' + extension.icon + ')'; + item.querySelector('.extension-title').textContent = extension.name; + item.querySelector('.extension-version').textContent = extension.version; + item.querySelector('.extension-description').textContent = + extension.description; + } + + function handleExtensionActivity(result) { + var template = $('template-collection'); + + var item = + template.querySelector('.extension-activity-item').cloneNode(true); + item.querySelector('.extension-activity-time').textContent = + new Date().toLocaleTimeString(); + item.querySelector('.extension-activity-label').textContent = + template.querySelector('.extension-activity-label-' + result.activity) + .textContent; + item.querySelector('.extension-activity-message').textContent = + result.message; + + $('extension-activity-list').appendChild(item); + } + + return { + initialize: initialize, + handleExtensionData: handleExtensionData, + handleExtensionActivity: handleExtensionActivity + }; +}); + +document.addEventListener('DOMContentLoaded', extension_activity.initialize); diff --git a/chrome/browser/resources/extensions/extension_list.js b/chrome/browser/resources/extensions/extension_list.js index 0da6cc0..e8bb8c1 100644 --- a/chrome/browser/resources/extensions/extension_list.js +++ b/chrome/browser/resources/extensions/extension_list.js @@ -147,6 +147,13 @@ cr.define('options', function() { e.preventDefault(); }); + if (extension.allow_activity) { + var activity = node.querySelector('.activity-link'); + activity.href = 'chrome://extension-activity?extensionId=' + + extension.id; + activity.hidden = false; + } + // The 'View in Web Store' checkbox. if (extension.homepageUrl) { var store = node.querySelector('.store-link'); diff --git a/chrome/browser/resources/extensions/extensions.html b/chrome/browser/resources/extensions/extensions.html index f828ada..5bd3e7d 100644 --- a/chrome/browser/resources/extensions/extensions.html +++ b/chrome/browser/resources/extensions/extensions.html @@ -110,6 +110,8 @@ </label> <a class="options-link" i18n-content="extensionSettingsOptions" href="#"></a> + <a class="activity-link" i18n-content="extensionSettingsActivity" + href="#" hidden></a> <a class="store-link" i18n-content="extensionSettingsVisitWebsite" target="_parent" hidden></a> <a class="reload-link" i18n-content="extensionSettingsReload" diff --git a/chrome/browser/resources/options/extension_list.js b/chrome/browser/resources/options/extension_list.js index 5cbad97..d674c47 100644 --- a/chrome/browser/resources/options/extension_list.js +++ b/chrome/browser/resources/options/extension_list.js @@ -1,4 +1,4 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -222,6 +222,15 @@ cr.define('options', function() { vbox.appendChild(link); } + if (extension.allow_activity) { + var link = this.ownerDocument.createElement('a'); + link.classList.add('extension-links-trailing'); + link.textContent = + localStrings.getString('extensionSettingsActivity'); + link.href = 'chrome://extension-activity?extensionId=' + extension.id; + vbox.appendChild(link); + } + // Then the optional Visit Website link. if (extension.homepageUrl) { var link = this.ownerDocument.createElement('a'); diff --git a/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc b/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc index f41f6e0..8165aa7 100644 --- a/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc +++ b/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc @@ -21,6 +21,7 @@ #include "chrome/browser/ui/webui/devtools_ui.h" #include "chrome/browser/ui/webui/downloads_ui.h" #include "chrome/browser/ui/webui/edit_search_engine_dialog_ui_webui.h" +#include "chrome/browser/ui/webui/extensions/extension_activity_ui.h" #include "chrome/browser/ui/webui/extensions/extensions_ui.h" #include "chrome/browser/ui/webui/feedback_ui.h" #include "chrome/browser/ui/webui/task_manager_ui.h" @@ -343,6 +344,12 @@ WebUIFactoryFunction GetWebUIFactoryFunction(content::WebUI* web_ui, return &NewWebUI<AboutUI>; } + if (url.host() == chrome::kChromeUIExtensionActivityHost && + CommandLine::ForCurrentProcess()->HasSwitch( + switches::kEnableExtensionActivityUI)) { + return &NewWebUI<ExtensionActivityUI>; + } + DLOG(WARNING) << "Unknown WebUI:" << url; return NULL; } diff --git a/chrome/browser/ui/webui/extensions/extension_activity_ui.cc b/chrome/browser/ui/webui/extensions/extension_activity_ui.cc new file mode 100644 index 0000000..dbcb6fa --- /dev/null +++ b/chrome/browser/ui/webui/extensions/extension_activity_ui.cc @@ -0,0 +1,101 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ui/webui/extensions/extension_activity_ui.h" + +#include "base/bind.h" +#include "chrome/browser/extensions/extension_service.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/ui/webui/chrome_web_ui_data_source.h" +#include "chrome/browser/ui/webui/extensions/extension_icon_source.h" +#include "chrome/browser/ui/webui/shared_resources_data_source.h" +#include "chrome/common/url_constants.h" +#include "content/public/browser/web_ui.h" +#include "grit/browser_resources.h" +#include "grit/generated_resources.h" +#include "ui/base/l10n/l10n_util.h" + +ExtensionActivityUI::ExtensionActivityUI(content::WebUI* web_ui) + : WebUIController(web_ui), extension_(NULL) { + web_ui->HideURL(); + web_ui->OverrideTitle(l10n_util::GetStringUTF16( + IDS_EXTENSION_ACTIVITY_TITLE)); + + ChromeWebUIDataSource* source = + new ChromeWebUIDataSource(chrome::kChromeUIExtensionActivityHost); + + // Localized strings. + source->AddLocalizedString("extensionActivity", IDS_EXTENSION_ACTIVITY_TITLE); + source->AddLocalizedString("extensionActivityApiCall", + IDS_EXTENSION_ACTIVITY_API_CALL); + source->AddLocalizedString("extensionActivityApiBlock", + IDS_EXTENSION_ACTIVITY_API_BLOCK); + source->set_json_path("strings.js"); + + // Resources. + source->add_resource_path("extension_activity.js", IDR_EXTENSION_ACTIVITY_JS); + source->set_default_resource(IDR_EXTENSION_ACTIVITY_HTML); + + // Callback handlers. + web_ui->RegisterMessageCallback("requestExtensionData", + base::Bind(&ExtensionActivityUI::HandleRequestExtensionData, + base::Unretained(this))); + + Profile* profile = Profile::FromWebUI(web_ui); + profile->GetChromeURLDataManager()->AddDataSource(source); + profile->GetChromeURLDataManager()->AddDataSource( + new SharedResourcesDataSource()); +} + +ExtensionActivityUI::~ExtensionActivityUI() { + if (extension_) + ExtensionActivityLog::GetInstance()->RemoveObserver(extension_, this); +} + +void ExtensionActivityUI::HandleRequestExtensionData( + const base::ListValue* args) { + DCHECK_EQ(1U, args->GetSize()); + + std::string extension_id; + if (!args->GetString(0, &extension_id)) + return; + + ExtensionService* extension_service = Profile::FromWebUI(web_ui())-> + GetExtensionService(); + extension_ = extension_service->GetExtensionById(extension_id, false); + if (!extension_) + return; + + GURL icon = + ExtensionIconSource::GetIconURL(extension_, + Extension::EXTENSION_ICON_MEDIUM, + ExtensionIconSet::MATCH_BIGGER, + false, NULL); + + DictionaryValue* extension_data = new DictionaryValue(); // Owned by result. + extension_data->SetString("id", extension_->id()); + extension_data->SetString("name", extension_->name()); + extension_data->SetString("version", extension_->version()->GetString()); + extension_data->SetString("description", extension_->description()); + extension_data->SetString("icon", icon.spec()); + + DictionaryValue result; + result.Set("extension", extension_data); + + web_ui()->CallJavascriptFunction("extension_activity.handleExtensionData", + result); + + ExtensionActivityLog::GetInstance()->AddObserver(extension_, this); +} + +void ExtensionActivityUI::OnExtensionActivity( + const Extension* extension, + ExtensionActivityLog::Activity activity, + const std::string& msg) { + DictionaryValue result; + result.SetInteger("activity", activity); + result.SetString("message", msg); + 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 new file mode 100644 index 0000000..54728ed --- /dev/null +++ b/chrome/browser/ui/webui/extensions/extension_activity_ui.h @@ -0,0 +1,32 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_UI_WEBUI_EXTENSIONS_EXTENSION_ACTIVITY_UI_H_ +#define CHROME_BROWSER_UI_WEBUI_EXTENSIONS_EXTENSION_ACTIVITY_UI_H_ +#pragma once + +#include "chrome/browser/extensions/extension_activity_log.h" +#include "content/public/browser/web_ui_controller.h" + +class ExtensionActivityUI : public content::WebUIController, + public ExtensionActivityLog::Observer { + public: + explicit ExtensionActivityUI(content::WebUI* web_ui); + virtual ~ExtensionActivityUI(); + + // Callback for "requestExtensionData". + void HandleRequestExtensionData(const base::ListValue* args); + + // ExtensionActivityLog::Observer implementation. + virtual void OnExtensionActivity(const Extension* extension, + ExtensionActivityLog::Activity activity, + const std::string& msg) OVERRIDE; + + private: + const Extension* extension_; + + DISALLOW_COPY_AND_ASSIGN(ExtensionActivityUI); +}; + +#endif // CHROME_BROWSER_UI_WEBUI_EXTENSIONS_EXTENSION_ACTIVITY_UI_H_ diff --git a/chrome/browser/ui/webui/options/extension_settings_handler.cc b/chrome/browser/ui/webui/options/extension_settings_handler.cc index f439cf9..b5fb903 100644 --- a/chrome/browser/ui/webui/options/extension_settings_handler.cc +++ b/chrome/browser/ui/webui/options/extension_settings_handler.cc @@ -548,6 +548,8 @@ void ExtensionSettingsHandler::GetLocalizedValues( l10n_util::GetStringUTF16(IDS_EXTENSIONS_RELOAD)); localized_strings->SetString("extensionSettingsOptions", l10n_util::GetStringUTF16(IDS_EXTENSIONS_OPTIONS_LINK)); + localized_strings->SetString("extensionSettingsActivity", + l10n_util::GetStringUTF16(IDS_EXTENSIONS_ACTIVITY_LINK)); localized_strings->SetString("extensionSettingsPolicyControlled", l10n_util::GetStringUTF16(IDS_EXTENSIONS_POLICY_CONTROLLED)); localized_strings->SetString("extensionSettingsShowButton", @@ -666,6 +668,9 @@ DictionaryValue* ExtensionSettingsHandler::CreateExtensionDetailValue( extension_data->SetBoolean("wantsFileAccess", extension->wants_file_access()); extension_data->SetBoolean("allowFileAccess", service ? service->AllowFileAccess(extension) : false); + extension_data->SetBoolean("allow_activity", + enabled && CommandLine::ForCurrentProcess()->HasSwitch( + switches::kEnableExtensionActivityUI)); extension_data->SetBoolean("allow_reload", extension->location() == Extension::LOAD); extension_data->SetBoolean("is_hosted_app", extension->is_hosted_app()); diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi index ae19796..f05e5d9 100644 --- a/chrome/chrome_browser.gypi +++ b/chrome/chrome_browser.gypi @@ -3837,6 +3837,8 @@ 'browser/ui/webui/edit_search_engine_dialog_webui.h', 'browser/ui/webui/edit_search_engine_dialog_ui_webui.cc', 'browser/ui/webui/edit_search_engine_dialog_ui_webui.h', + 'browser/ui/webui/extensions/extension_activity_ui.cc', + 'browser/ui/webui/extensions/extension_activity_ui.h', 'browser/ui/webui/extensions/extension_icon_source.cc', 'browser/ui/webui/extensions/extension_icon_source.h', 'browser/ui/webui/extensions/extensions_ui.cc', diff --git a/chrome/common/chrome_switches.cc b/chrome/common/chrome_switches.cc index 4adb1e2..dda6909 100644 --- a/chrome/common/chrome_switches.cc +++ b/chrome/common/chrome_switches.cc @@ -503,6 +503,9 @@ const char kEnableExperimentalExtensionApis[] = const char kEnableExtensionActivityLogging[] = "enable-extension-activity-logging"; +// Enables the extension activity UI. +const char kEnableExtensionActivityUI[] = "enable-extension-activity-ui"; + // Enables experimental timeline API. const char kEnableExtensionTimelineApi[] = "enable-extension-timeline-api"; diff --git a/chrome/common/chrome_switches.h b/chrome/common/chrome_switches.h index 4dbeb1c8b..bdaaf31 100644 --- a/chrome/common/chrome_switches.h +++ b/chrome/common/chrome_switches.h @@ -144,6 +144,7 @@ extern const char kEnableCrxlessWebApps[]; extern const char kEnableDevToolsExperiments[]; extern const char kEnableExperimentalExtensionApis[]; extern const char kEnableExtensionActivityLogging[]; +extern const char kEnableExtensionActivityUI[]; extern const char kEnableExtensionTimelineApi[]; extern const char kEnableFastback[]; extern const char kEnableFileCookies[]; diff --git a/chrome/common/url_constants.cc b/chrome/common/url_constants.cc index 177f4cc..c1514b9 100644 --- a/chrome/common/url_constants.cc +++ b/chrome/common/url_constants.cc @@ -40,6 +40,7 @@ const char kChromeUICreditsURL[] = "chrome://credits/"; const char kChromeUIDevToolsURL[] = "chrome-devtools://devtools/"; const char kChromeUIDownloadsURL[] = "chrome://downloads/"; const char kChromeUIEditSearchEngineDialogURL[] = "chrome://editsearchengine/"; +const char kChromeUIExtensionActivityURL[] = "chrome://extension-activity/"; const char kChromeUIExtensionIconURL[] = "chrome://extension-icon/"; const char kChromeUIExtensionsFrameURL[] = "chrome://extensions-frame/"; const char kChromeUIExtensionsURL[] = "chrome://extensions/"; @@ -142,6 +143,7 @@ const char kChromeUIDialogHost[] = "dialog"; const char kChromeUIDNSHost[] = "dns"; const char kChromeUIDownloadsHost[] = "downloads"; const char kChromeUIEditSearchEngineDialogHost[] = "editsearchengine"; +const char kChromeUIExtensionActivityHost[] = "extension-activity"; const char kChromeUIExtensionIconHost[] = "extension-icon"; const char kChromeUIExtensionsFrameHost[] = "extensions-frame"; const char kChromeUIExtensionsHost[] = "extensions"; diff --git a/chrome/common/url_constants.h b/chrome/common/url_constants.h index bfad3c9..4666b00 100644 --- a/chrome/common/url_constants.h +++ b/chrome/common/url_constants.h @@ -33,6 +33,7 @@ extern const char kChromeUICreditsURL[]; extern const char kChromeUIDevToolsURL[]; extern const char kChromeUIDownloadsURL[]; extern const char kChromeUIEditSearchEngineDialogURL[]; +extern const char kChromeUIExtensionActivityURL[]; extern const char kChromeUIExtensionIconURL[]; extern const char kChromeUIExtensionsFrameURL[]; extern const char kChromeUIExtensionsURL[]; @@ -129,6 +130,7 @@ extern const char kChromeUIDialogHost[]; extern const char kChromeUIDNSHost[]; extern const char kChromeUIDownloadsHost[]; extern const char kChromeUIEditSearchEngineDialogHost[]; +extern const char kChromeUIExtensionActivityHost[]; extern const char kChromeUIExtensionIconHost[]; extern const char kChromeUIExtensionsFrameHost[]; extern const char kChromeUIExtensionsHost[]; |