diff options
18 files changed, 975 insertions, 5 deletions
diff --git a/chrome/browser/browser_resources.grd b/chrome/browser/browser_resources.grd index 5850728..a1f4e6d 100644 --- a/chrome/browser/browser_resources.grd +++ b/chrome/browser/browser_resources.grd @@ -84,6 +84,7 @@ without changes to the corresponding grd file. etaa --> <include name="IDR_WEBSTORE_MANIFEST" file="resources\webstore_app\manifest.json" type="BINDATA" /> <if expr="pp_ifdef('chromeos')"> <include name="IDR_ABOUT_SYS_HTML" file="resources\about_sys.html" flattenhtml="true" type="BINDATA" /> + <include name="IDR_COLLECTED_COOKIES_HTML" file="resources\collected_cookies.html" flattenhtml="true" type="BINDATA" /> <include name="IDR_GUEST_SESSION_TAB_HTML" file="resources\guest_session_tab.html" flattenhtml="true" type="BINDATA" /> <include name="IDR_FILEBROWSE_HTML" file="resources\filebrowse.html" flattenhtml="true" type="BINDATA" /> <include name="IDR_HOST_REGISTRATION_PAGE_HTML" file="resources\host_registration_page.html" flattenhtml="true" type="BINDATA" /> diff --git a/chrome/browser/resources/collected_cookies.css b/chrome/browser/resources/collected_cookies.css new file mode 100644 index 0000000..18217b9 --- /dev/null +++ b/chrome/browser/resources/collected_cookies.css @@ -0,0 +1,16 @@ +body { + font-size: 84%; + font-family: Arial, Helvetica, sans-serif; +} + +.cookies-tree { + border: 1px solid lightgrey; + padding: 5px; + width: 450px; + height: 135px; +} + +#info-banner { + background: -webkit-linear-gradient(#fff2b7, #fae691 97%, #878787); + padding: 2px 0; +} diff --git a/chrome/browser/resources/collected_cookies.html b/chrome/browser/resources/collected_cookies.html new file mode 100644 index 0000000..293e11f --- /dev/null +++ b/chrome/browser/resources/collected_cookies.html @@ -0,0 +1,35 @@ +<!DOCTYPE HTML> +<html i18n-values="dir:textdirection;"> + +<head> +<meta charset="utf-8"> +<title i18n-content="title"></title> +<link rel="stylesheet" href="chrome://resources/css/tree.css"> +<link rel="stylesheet" href="collected_cookies.css"> +</head> + +<script src="chrome://resources/css/tree.css.js"></script> + +<script src="chrome://resources/js/cr.js"></script> +<script src="chrome://resources/js/cr/ui.js"></script> +<script src="chrome://resources/js/cr/ui/tree.js"></script> +<script src="chrome://resources/js/util.js"></script> +<script src="cookies_tree.js"></script> +<script src="collected_cookies.js"></script> + +<body> + +<div id="info-banner" hidden></div> + +<p i18n-content="allowedCookies"></p> +<tree id="allowed-cookies" class="cookies-tree"></tree> +<button id="block-button" i18n-content="blockButton"></button> + +<p i18n-content="blockedCookies"></p> +<tree id="blocked-cookies" class="cookies-tree"></tree> +<button id="allow-button" i18n-content="allowButton"></button> +<button id="allow-this-session-button" + i18n-content="allowThisSessionButton"></button> +<button id="close-button" i18n-content="closeButton"></button> +</body> +</html> diff --git a/chrome/browser/resources/collected_cookies.js b/chrome/browser/resources/collected_cookies.js new file mode 100644 index 0000000..ca3cbb0 --- /dev/null +++ b/chrome/browser/resources/collected_cookies.js @@ -0,0 +1,79 @@ +// Copyright (c) 2011 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. + +function closeDialog() { + chrome.send('DialogClose', ['']); +} + +function setInfobarLabel(text) { + $('info-banner').textContent = text; + $('info-banner').hidden = !text.length; +} + +function updateControlState() { + var allowedCookies = $('allowed-cookies'); + $('block-button').disabled = !allowedCookies.children.length || + !allowedCookies.selectedItem || + allowedCookies.selectedItem.data.type != 'origin'; + + var blockedCookies = $('blocked-cookies'); + $('allow-button').disabled = + $('allow-this-session-button').disabled = !blockedCookies.children.length || + !blockedCookies.selectedItem || + blockedCookies.selectedItem.data.type != 'origin'; +} + +function handleCookiesTreeChange(e) { + updateControlState(); +} + +function handleBlockButtonClick(e) { + var selected = $('allowed-cookies').selectedItem; + if (!selected) + return; + + chrome.send('Block', [selected.pathId]); +} + +function handleAllowButtonClick(e) { + var selected = $('blocked-cookies').selectedItem; + if (selected) + chrome.send('Allow', [selected.pathId]); +} + +function handleAllowThisSessionButtonClick(e) { + var selected = $('blocked-cookies').selectedItem; + if (selected) + chrome.send('AllowThisSession', [selected.pathId]); +} + +function load() { + ui.CookiesTree.decorate($('allowed-cookies')); + ui.CookiesTree.decorate($('blocked-cookies')); + + chrome.send('BindCookiesTreeModel', []); + + $('allowed-cookies').addEventListener('change', handleCookiesTreeChange); + $('blocked-cookies').addEventListener('change', handleCookiesTreeChange); + + $('block-button').addEventListener('click', handleBlockButtonClick); + $('allow-button').addEventListener('click', handleAllowButtonClick); + $('allow-this-session-button').addEventListener('click', + handleAllowThisSessionButtonClick); + + $('close-button').addEventListener('click', closeDialog); + + document.oncontextmenu = function(e) { + e.preventDefault(); + } + + document.onkeydown = function(e) { + if (e.keyCode == 27) // Esc + closeDialog(); + } + + updateControlState(); +} + +document.addEventListener('DOMContentLoaded', load); diff --git a/chrome/browser/resources/cookies_tree.js b/chrome/browser/resources/cookies_tree.js new file mode 100644 index 0000000..42187de --- /dev/null +++ b/chrome/browser/resources/cookies_tree.js @@ -0,0 +1,224 @@ +// Copyright (c) 2010 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('ui', function() { + const Tree = cr.ui.Tree; + const TreeItem = cr.ui.TreeItem; + + /** + * Creates a new tree item for sites data. + * @param {Object=} data Data used to create a cookie tree item. + * @constructor + * @extends {TreeItem} + */ + function CookiesTreeItem(data) { + var treeItem = new TreeItem({ + label: data.title, + data: data + }); + treeItem.__proto__ = CookiesTreeItem.prototype; + + if (data.icon) + treeItem.icon = data.icon; + + treeItem.decorate(); + return treeItem; + } + + CookiesTreeItem.prototype = { + __proto__: TreeItem.prototype, + + /** @inheritDoc */ + decorate: function() { + this.hasChildren = this.data.hasChildren; + }, + + /** @inheritDoc */ + addAt: function(child, index) { + TreeItem.prototype.addAt.call(this, child, index); + if (child.data && child.data.id) + this.tree.treeLookup[child.data.id] = child; + }, + + /** @inheritDoc */ + remove: function(child) { + TreeItem.prototype.remove.call(this, child); + if (child.data && child.data.id) + delete this.tree.treeLookup[child.data.id]; + }, + + /** + * Clears all children. + */ + clear: function() { + // We might leave some garbage in treeLookup for removed children. + // But that should be okay because treeLookup is cleared when we + // reload the tree. + this.lastElementChild.textContent = ''; + }, + + /** + * The tree path id. + * @type {string} + */ + get pathId() { + var parent = this.parentItem; + if (parent instanceof CookiesTreeItem) + return parent.pathId + ',' + this.data.id; + else + return this.data.id; + }, + + /** @inheritDoc */ + get expanded() { + return TreeItem.prototype.__lookupGetter__('expanded').call(this); + }, + set expanded(b) { + if (b && this.expanded != b) + chrome.send(this.tree.requestChildrenMessage, [this.pathId]); + + TreeItem.prototype.__lookupSetter__('expanded').call(this, b); + } + }; + + /** + * Creates a new cookies tree. + * @param {Object=} opt_propertyBag Optional properties. + * @constructor + * @extends {Tree} + */ + var CookiesTree = cr.ui.define('tree'); + + CookiesTree.prototype = { + __proto__: Tree.prototype, + + /** + * Per-tree dict to map from data.id to tree node. + */ + treeLookup_: null, + get treeLookup() { + if (!this.treeLookup_) + this.treeLookup_ = {}; + return this.treeLookup_; + }, + + /** @inheritDoc */ + addAt: function(child, index) { + Tree.prototype.addAt.call(this, child, index); + if (child.data && child.data.id) + this.treeLookup[child.data.id] = child; + }, + + /** @inheritDoc */ + remove: function(child) { + Tree.prototype.remove.call(this, child); + if (child.data && child.data.id) + delete this.treeLookup[child.data.id]; + }, + + /** + * Add tree nodes by given parent. + * @param {Object} parent Parent node. + * @param {number} start Start index of where to insert nodes. + * @param {Array} nodesData Nodes data array. + */ + addByParent: function(parent, start, nodesData) { + for (var i = 0; i < nodesData.length; ++i) { + parent.addAt(new CookiesTreeItem(nodesData[i]), start + i); + } + + cr.dispatchSimpleEvent(this, 'change'); + }, + + /** + * Add tree nodes by parent id. + * @param {string} parentId Id of the parent node. + * @param {int} start Start index of where to insert nodes. + * @param {Array} nodesData Nodes data array. + */ + addByParentId: function(parentId, start, nodesData) { + var parent = parentId ? this.treeLookup[parentId] : this; + this.addByParent(parent, start, nodesData); + }, + + /** + * Removes tree nodes by parent id. + * @param {string} parentId Id of the parent node. + * @param {int} start Start index of nodes to remove. + * @param {int} count Number of nodes to remove. + */ + removeByParentId: function(parentId, start, count) { + var parent = parentId ? this.treeLookup[parentId] : this; + + for (; count > 0 && parent.items.length; --count) { + parent.remove(parent.items[start]); + } + + cr.dispatchSimpleEvent(this, 'change'); + }, + + /** + * Clears the tree. + */ + clear: function() { + // Remove all fields without recreating the object since other code + // references it. + for (var id in this.treeLookup){ + delete this.treeLookup[id]; + } + this.textContent = ''; + }, + + /** + * Unique 'requestChildren' callback message name to send request to + * underlying CookiesTreeModelAdapter. + * @type {string} + */ + requestChildrenMessage_ : null, + get requestChildrenMessage() { + return this.requestChildrenMessage_; + }, + + /** + * Set callback message name. + * @param {string} loadChildren Message name for 'loadChildren' request. + */ + doSetCallback: function(loadChildren) { + this.requestChildrenMessage_ = loadChildren; + }, + + /** + * Sets the immediate children of given parent node. + * @param {string} parentId Id of the parent node. + * @param {Array} children The immediate children of parent node. + */ + doSetChildren: function(parentId, children) { + var parent = parentId ? this.treeLookup[parentId] : this; + + parent.clear(); + this.addByParent(parent, 0, children); + } + }; + + // CookiesTreeModelAdapter callbacks. + CookiesTree.setCallback = function(treeId, message) { + $(treeId).doSetCallback(message); + } + + CookiesTree.onTreeItemAdded = function(treeId, parentId, start, children) { + $(treeId).addByParentId(parentId, start, children); + } + + CookiesTree.onTreeItemRemoved = function(treeId, parentId, start, count) { + $(treeId).removeByParentId(parentId, start, count); + } + + CookiesTree.setChildren = function(treeId, parentId, children) { + $(treeId).doSetChildren(parentId, children); + } + + return { + CookiesTree: CookiesTree + }; +}); diff --git a/chrome/browser/ui/gtk/constrained_html_delegate_gtk.cc b/chrome/browser/ui/gtk/constrained_html_delegate_gtk.cc index 26deb64..af42724 100644 --- a/chrome/browser/ui/gtk/constrained_html_delegate_gtk.cc +++ b/chrome/browser/ui/gtk/constrained_html_delegate_gtk.cc @@ -19,7 +19,7 @@ class ConstrainedHtmlDelegateGtk : public ConstrainedWindowGtkDelegate, public ConstrainedHtmlUIDelegate { public: ConstrainedHtmlDelegateGtk(Profile* profile, - HtmlDialogUIDelegate* delegate); + HtmlDialogUIDelegate* delegate); virtual ~ConstrainedHtmlDelegateGtk(); diff --git a/chrome/browser/ui/gtk/constrained_window_gtk.cc b/chrome/browser/ui/gtk/constrained_window_gtk.cc index 2a454ce..a3650a6 100644 --- a/chrome/browser/ui/gtk/constrained_window_gtk.cc +++ b/chrome/browser/ui/gtk/constrained_window_gtk.cc @@ -24,6 +24,10 @@ bool ConstrainedWindowGtkDelegate::GetBackgroundColor(GdkColor* color) { return false; } +bool ConstrainedWindowGtkDelegate::ShouldHaveBorderPadding() const { + return true; +} + ConstrainedWindowGtk::ConstrainedWindowGtk( TabContents* owner, ConstrainedWindowGtkDelegate* delegate) : owner_(owner), @@ -41,9 +45,12 @@ ConstrainedWindowGtk::ConstrainedWindowGtk( gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_OUT); GtkWidget* alignment = gtk_alignment_new(0.0, 0.0, 1.0, 1.0); - gtk_alignment_set_padding(GTK_ALIGNMENT(alignment), - gtk_util::kContentAreaBorder, gtk_util::kContentAreaBorder, - gtk_util::kContentAreaBorder, gtk_util::kContentAreaBorder); + if (delegate->ShouldHaveBorderPadding()) { + gtk_alignment_set_padding(GTK_ALIGNMENT(alignment), + gtk_util::kContentAreaBorder, gtk_util::kContentAreaBorder, + gtk_util::kContentAreaBorder, gtk_util::kContentAreaBorder); + } + GdkColor background; if (delegate->GetBackgroundColor(&background)) { gtk_widget_modify_base(ebox, GTK_STATE_NORMAL, &background); diff --git a/chrome/browser/ui/gtk/constrained_window_gtk.h b/chrome/browser/ui/gtk/constrained_window_gtk.h index 90cd2ea..51b4cb2 100644 --- a/chrome/browser/ui/gtk/constrained_window_gtk.h +++ b/chrome/browser/ui/gtk/constrained_window_gtk.h @@ -36,6 +36,9 @@ class ConstrainedWindowGtkDelegate { virtual bool GetBackgroundColor(GdkColor* color); + // Returns true if hosting ConstrainedWindowGtk should apply default padding. + virtual bool ShouldHaveBorderPadding() const; + protected: virtual ~ConstrainedWindowGtkDelegate(); }; diff --git a/chrome/browser/ui/views/constrained_html_delegate_gtk.cc b/chrome/browser/ui/views/constrained_html_delegate_gtk.cc index 3fdd72c..223f643 100644 --- a/chrome/browser/ui/views/constrained_html_delegate_gtk.cc +++ b/chrome/browser/ui/views/constrained_html_delegate_gtk.cc @@ -44,6 +44,9 @@ class ConstrainedHtmlDelegateGtk : public views::WidgetGtk, html_delegate_->OnDialogClosed(""); tab_container_->ChangeTabContents(NULL); } + virtual bool ShouldHaveBorderPadding() const { + return false; + } // HtmlDialogTabContentsDelegate interface. void MoveContents(TabContents* source, const gfx::Rect& pos) {} diff --git a/chrome/browser/ui/views/dialog_stubs_gtk.cc b/chrome/browser/ui/views/dialog_stubs_gtk.cc index b455bf8..b5214ee 100644 --- a/chrome/browser/ui/views/dialog_stubs_gtk.cc +++ b/chrome/browser/ui/views/dialog_stubs_gtk.cc @@ -21,6 +21,7 @@ #include "chrome/browser/ui/options/options_window.h" #include "chrome/browser/ui/views/browser_dialogs.h" #include "content/browser/tab_contents/tab_contents.h" +#include "chrome/browser/ui/webui/collected_cookies_ui_delegate.h" #include "views/widget/widget.h" namespace browser { @@ -67,7 +68,11 @@ void ShowContentSettingsWindow(gfx::NativeWindow parent_window, void ShowCollectedCookiesDialog(gfx::NativeWindow parent_window, TabContents* tab_contents) { +#if defined(OS_CHROMEOS) + CollectedCookiesUIDelegate::Show(tab_contents); +#else new CollectedCookiesGtk(GTK_WINDOW(parent_window), tab_contents); +#endif } } // namespace browser diff --git a/chrome/browser/ui/webui/collected_cookies_ui_delegate.cc b/chrome/browser/ui/webui/collected_cookies_ui_delegate.cc new file mode 100644 index 0000000..6909769 --- /dev/null +++ b/chrome/browser/ui/webui/collected_cookies_ui_delegate.cc @@ -0,0 +1,288 @@ +// Copyright (c) 2011 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/collected_cookies_ui_delegate.h" + +#include "base/message_loop.h" +#include "base/string_util.h" +#include "base/values.h" +#include "chrome/browser/cookies_tree_model.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/ui/webui/chrome_url_data_manager.h" +#include "chrome/browser/ui/webui/constrained_html_ui.h" +#include "chrome/browser/ui/webui/cookies_tree_model_util.h" +#include "chrome/common/jstemplate_builder.h" +#include "chrome/common/url_constants.h" +#include "content/browser/tab_contents/tab_contents.h" +#include "content/common/notification_service.h" +#include "grit/browser_resources.h" +#include "grit/generated_resources.h" +#include "ui/base/l10n/l10n_util.h" +#include "ui/base/resource/resource_bundle.h" + +namespace { + +// TODO(xiyuan): Localize this. +const int kDialogWidth = 480; +const int kDialogHeight = 470; + +CookieTreeOriginNode* GetOriginNode(CookiesTreeModel* model, + const std::string& node_path) { + CookieTreeNode* node = cookies_tree_model_util::GetTreeNodeFromPath( + model->GetRoot(), node_path); + + while (node && node->GetDetailedInfo().node_type != + CookieTreeNode::DetailedInfo::TYPE_ORIGIN) { + node = node->parent(); + } + + return static_cast<CookieTreeOriginNode*>(node); +} + +std::string GetInfobarLabel(ContentSetting setting, + const string16& domain_name) { + switch (setting) { + case CONTENT_SETTING_BLOCK: + return l10n_util::GetStringFUTF8( + IDS_COLLECTED_COOKIES_BLOCK_RULE_CREATED, domain_name); + + case CONTENT_SETTING_ALLOW: + return l10n_util::GetStringFUTF8( + IDS_COLLECTED_COOKIES_ALLOW_RULE_CREATED, domain_name); + + case CONTENT_SETTING_SESSION_ONLY: + return l10n_util::GetStringFUTF8( + IDS_COLLECTED_COOKIES_SESSION_RULE_CREATED, domain_name); + + default: + NOTREACHED() << "Unknown ContentSetting, " << setting; + return std::string(); + } +} + +class CollectedCookiesSource : public ChromeURLDataManager::DataSource { + public: + explicit CollectedCookiesSource(bool block_third_party_cookies) + : DataSource(chrome::kChromeUICollectedCookiesHost, + MessageLoop::current()), + block_third_party_cookies_(block_third_party_cookies) { + } + + virtual void StartDataRequest(const std::string& path, + bool is_off_the_record, + int request_id); + + virtual std::string GetMimeType(const std::string& path) const { + return "text/html"; + } + + private: + virtual ~CollectedCookiesSource() {} + + bool block_third_party_cookies_; + + DISALLOW_COPY_AND_ASSIGN(CollectedCookiesSource); +}; + +void CollectedCookiesSource::StartDataRequest(const std::string& path, + bool is_off_the_record, + int request_id) { + DictionaryValue localized_strings; + localized_strings.SetString("title", + l10n_util::GetStringUTF16(IDS_COLLECTED_COOKIES_DIALOG_TITLE)); + + localized_strings.SetString("title", + l10n_util::GetStringUTF16(IDS_COLLECTED_COOKIES_DIALOG_TITLE)); + localized_strings.SetString("allowedCookies", + l10n_util::GetStringUTF16(IDS_COLLECTED_COOKIES_ALLOWED_COOKIES_LABEL)); + localized_strings.SetString("blockButton", + l10n_util::GetStringUTF16(IDS_COLLECTED_COOKIES_BLOCK_BUTTON)); + + localized_strings.SetString("blockedCookies", + l10n_util::GetStringUTF16(block_third_party_cookies_ ? + IDS_COLLECTED_COOKIES_BLOCKED_THIRD_PARTY_BLOCKING_ENABLED : + IDS_COLLECTED_COOKIES_BLOCKED_COOKIES_LABEL)); + + localized_strings.SetString("allowButton", + l10n_util::GetStringUTF16(IDS_COLLECTED_COOKIES_ALLOW_BUTTON)); + localized_strings.SetString("allowThisSessionButton", + l10n_util::GetStringUTF16(IDS_COLLECTED_COOKIES_SESSION_ONLY_BUTTON)); + localized_strings.SetString("closeButton", + l10n_util::GetStringUTF16(IDS_CLOSE)); + + SetFontAndTextDirection(&localized_strings); + + static const base::StringPiece html( + ResourceBundle::GetSharedInstance().GetRawDataResource( + IDR_COLLECTED_COOKIES_HTML)); + const std::string response = jstemplate_builder::GetI18nTemplateHtml( + html, &localized_strings); + + scoped_refptr<RefCountedBytes> html_bytes(new RefCountedBytes); + html_bytes->data.resize(response.size()); + std::copy(response.begin(), response.end(), html_bytes->data.begin()); + + SendResponse(request_id, html_bytes); +} + +} // namespace + +// static +void CollectedCookiesUIDelegate::Show(TabContents* tab_contents) { + CollectedCookiesUIDelegate* delegate = + new CollectedCookiesUIDelegate(tab_contents); + ConstrainedHtmlUI::CreateConstrainedHtmlDialog(tab_contents->profile(), + delegate, + tab_contents); +} + +CollectedCookiesUIDelegate::CollectedCookiesUIDelegate( + TabContents* tab_contents) + : tab_contents_(tab_contents), + closed_(false) { + TabSpecificContentSettings* content_settings = + tab_contents->GetTabSpecificContentSettings(); + HostContentSettingsMap* host_content_settings_map = + tab_contents_->profile()->GetHostContentSettingsMap(); + + registrar_.Add(this, NotificationType::COLLECTED_COOKIES_SHOWN, + Source<TabSpecificContentSettings>(content_settings)); + + allowed_cookies_tree_model_.reset( + content_settings->GetAllowedCookiesTreeModel()); + blocked_cookies_tree_model_.reset( + content_settings->GetBlockedCookiesTreeModel()); + + CollectedCookiesSource* source = new CollectedCookiesSource( + host_content_settings_map->BlockThirdPartyCookies()); + tab_contents->profile()->GetChromeURLDataManager()->AddDataSource(source); +} + +CollectedCookiesUIDelegate::~CollectedCookiesUIDelegate() { +} + +bool CollectedCookiesUIDelegate::IsDialogModal() const { + return false; +} + +std::wstring CollectedCookiesUIDelegate::GetDialogTitle() const { + return std::wstring(); +} + +GURL CollectedCookiesUIDelegate::GetDialogContentURL() const { + return GURL(chrome::kChromeUICollectedCookiesURL); +} + +void CollectedCookiesUIDelegate::GetWebUIMessageHandlers( + std::vector<WebUIMessageHandler*>* handlers) const { + const WebUIMessageHandler* handler = this; + handlers->push_back(const_cast<WebUIMessageHandler*>(handler)); +} + +void CollectedCookiesUIDelegate::GetDialogSize(gfx::Size* size) const { + size->set_width(kDialogWidth); + size->set_height(kDialogHeight); +} + +std::string CollectedCookiesUIDelegate::GetDialogArgs() const { + return std::string(); +} + +void CollectedCookiesUIDelegate::OnDialogClosed( + const std::string& json_retval) { + closed_ = true; +} + +bool CollectedCookiesUIDelegate::ShouldShowDialogTitle() const { + return true; +} + +void CollectedCookiesUIDelegate::RegisterMessages() { + web_ui_->RegisterMessageCallback("BindCookiesTreeModel", + NewCallback(this, &CollectedCookiesUIDelegate::BindCookiesTreeModel)); + web_ui_->RegisterMessageCallback("Block", + NewCallback(this, &CollectedCookiesUIDelegate::Block)); + web_ui_->RegisterMessageCallback("Allow", + NewCallback(this, &CollectedCookiesUIDelegate::Allow)); + web_ui_->RegisterMessageCallback("AllowThisSession", + NewCallback(this, &CollectedCookiesUIDelegate::AllowThisSession)); + + allowed_cookies_adapter_.Init(web_ui_); + blocked_cookies_adapter_.Init(web_ui_); +} + +void CollectedCookiesUIDelegate::CloseDialog() { + if (!closed_ && web_ui_) + web_ui_->CallJavascriptFunction("closeDialog"); +} + +void CollectedCookiesUIDelegate::SetInfobarLabel(const std::string& text) { + StringValue string(text); + web_ui_->CallJavascriptFunction("setInfobarLabel", string); +} + +void CollectedCookiesUIDelegate::AddContentException( + CookieTreeOriginNode* origin_node, ContentSetting setting) { + if (origin_node->CanCreateContentException()) { + origin_node->CreateContentException( + tab_contents_->profile()->GetHostContentSettingsMap(), setting); + + SetInfobarLabel(GetInfobarLabel(setting, origin_node->GetTitle())); + } +} + +void CollectedCookiesUIDelegate::Observe(NotificationType type, + const NotificationSource& source, + const NotificationDetails& details) { + DCHECK_EQ(type.value, NotificationType::COLLECTED_COOKIES_SHOWN); + DCHECK_EQ(Source<TabSpecificContentSettings>(source).ptr(), + tab_contents_->GetTabSpecificContentSettings()); + CloseDialog(); +} + +void CollectedCookiesUIDelegate::BindCookiesTreeModel(const ListValue* args) { + allowed_cookies_adapter_.Bind("allowed-cookies", + allowed_cookies_tree_model_.get()); + blocked_cookies_adapter_.Bind("blocked-cookies", + blocked_cookies_tree_model_.get()); +} + +void CollectedCookiesUIDelegate::Block(const ListValue* args) { + std::string node_path; + if (!args->GetString(0, &node_path)) + return; + + CookieTreeOriginNode* origin_node = GetOriginNode( + allowed_cookies_tree_model_.get(), node_path); + if (!origin_node) + return; + + AddContentException(origin_node, CONTENT_SETTING_BLOCK); +} + +void CollectedCookiesUIDelegate::Allow(const ListValue* args) { + std::string node_path; + if (!args->GetString(0, &node_path)) + return; + + CookieTreeOriginNode* origin_node = GetOriginNode( + blocked_cookies_tree_model_.get(), node_path); + if (!origin_node) + return; + + AddContentException(origin_node, CONTENT_SETTING_ALLOW); +} + +void CollectedCookiesUIDelegate::AllowThisSession(const ListValue* args) { + std::string node_path; + if (!args->GetString(0, &node_path)) + return; + + CookieTreeOriginNode* origin_node = GetOriginNode( + blocked_cookies_tree_model_.get(), node_path); + if (!origin_node) + return; + + AddContentException(origin_node, CONTENT_SETTING_SESSION_ONLY); +} diff --git a/chrome/browser/ui/webui/collected_cookies_ui_delegate.h b/chrome/browser/ui/webui/collected_cookies_ui_delegate.h new file mode 100644 index 0000000..c49766e --- /dev/null +++ b/chrome/browser/ui/webui/collected_cookies_ui_delegate.h @@ -0,0 +1,89 @@ +// Copyright (c) 2011 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_COLLECTED_COOKIES_UI_DELEGATE_H_ +#define CHROME_BROWSER_UI_WEBUI_COLLECTED_COOKIES_UI_DELEGATE_H_ +#pragma once + +#include <string> +#include <vector> + +#include "base/scoped_ptr.h" +#include "chrome/browser/ui/webui/cookies_tree_model_adapter.h" +#include "chrome/browser/ui/webui/html_dialog_ui.h" +#include "chrome/common/content_settings.h" +#include "content/common/notification_observer.h" +#include "content/common/notification_registrar.h" + +class GURL; +class TabContents; + +namespace gfx { +class Size; +} + +class CollectedCookiesUIDelegate : public HtmlDialogUIDelegate, + WebUIMessageHandler, + NotificationObserver { + public: + virtual ~CollectedCookiesUIDelegate(); + + // static factory method that shows CollectedCookiesUI for |tab_contents|. + static void Show(TabContents* tab_contents); + + // HtmlDialogUIDelegate implementation: + virtual bool IsDialogModal() const; + virtual std::wstring GetDialogTitle() const; + virtual GURL GetDialogContentURL() const; + virtual void GetWebUIMessageHandlers( + std::vector<WebUIMessageHandler*>* handlers) const; + virtual void GetDialogSize(gfx::Size* size) const; + virtual std::string GetDialogArgs() const; + virtual void OnDialogClosed(const std::string& json_retval); + virtual void OnCloseContents(TabContents* source, bool* out_close_dialog) {} + virtual bool ShouldShowDialogTitle() const; + + // WebUIMessageHandler implementation: + virtual void RegisterMessages(); + + private: + explicit CollectedCookiesUIDelegate(TabContents* tab_contents); + + // Closes the dialog from javascript. + void CloseDialog(); + + // Sets infobar label text. + void SetInfobarLabel(const std::string& text); + + // Add content exception. + void AddContentException(CookieTreeOriginNode* origin_node, + ContentSetting setting); + + // Notification Observer implementation. + void Observe(NotificationType type, + const NotificationSource& source, + const NotificationDetails& details); + + // JS callback to bind cookies tree models with JS trees. + void BindCookiesTreeModel(const ListValue* args); + + // JS callback to block/allow cookies from given site. + void Block(const ListValue* args); + void Allow(const ListValue* args); + void AllowThisSession(const ListValue* args); + + NotificationRegistrar registrar_; + TabContents* tab_contents_; + bool closed_; + + scoped_ptr<CookiesTreeModel> allowed_cookies_tree_model_; + scoped_ptr<CookiesTreeModel> blocked_cookies_tree_model_; + + CookiesTreeModelAdapter allowed_cookies_adapter_; + CookiesTreeModelAdapter blocked_cookies_adapter_; + + DISALLOW_COPY_AND_ASSIGN(CollectedCookiesUIDelegate); +}; + +#endif // CHROME_BROWSER_UI_WEBUI_COLLECTED_COOKIES_UI_DELEGATE_H_ diff --git a/chrome/browser/ui/webui/cookies_tree_model_adapter.cc b/chrome/browser/ui/webui/cookies_tree_model_adapter.cc new file mode 100644 index 0000000..03e04ea --- /dev/null +++ b/chrome/browser/ui/webui/cookies_tree_model_adapter.cc @@ -0,0 +1,135 @@ +// Copyright (c) 2011 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/cookies_tree_model_adapter.h" + +#include "base/scoped_ptr.h" +#include "base/string_number_conversions.h" +#include "base/values.h" +#include "chrome/browser/ui/webui/cookies_tree_model_util.h" +#include "content/browser/webui/web_ui.h" +#include "grit/generated_resources.h" +#include "ui/base/l10n/l10n_util.h" + +namespace { + +// Returns a unique callback name for |adapter|'s requestChildren. +std::string GetRequestChildrenCallbackName(CookiesTreeModelAdapter* adapter) { + static const char kPrefixLoadCookie[] = "requestChildren"; + return std::string(kPrefixLoadCookie) + + base::HexEncode(&adapter, sizeof(adapter)); +} + +} // namespace + +CookiesTreeModelAdapter::CookiesTreeModelAdapter() + : web_ui_(NULL), + model_(NULL), + batch_update_(false) { +} + +CookiesTreeModelAdapter::~CookiesTreeModelAdapter() { + if (model_) + model_->RemoveCookiesTreeObserver(this); +} + +void CookiesTreeModelAdapter::Init(WebUI* web_ui) { + web_ui_ = web_ui; + + web_ui_->RegisterMessageCallback(GetRequestChildrenCallbackName(this), + NewCallback(this, &CookiesTreeModelAdapter::RequestChildren)); +} + +void CookiesTreeModelAdapter::Bind(const std::string& tree_id, + CookiesTreeModel* model) { + DCHECK(web_ui_); // We should have been initialized. + DCHECK(tree_id_.empty() && !model_); // No existing bindings. + + tree_id_ = tree_id; + model_ = model; + model_->AddCookiesTreeObserver(this); + + StringValue tree_id_value(tree_id_); + StringValue message_name(GetRequestChildrenCallbackName(this)); + web_ui_->CallJavascriptFunction("ui.CookiesTree.setCallback", + tree_id_value, message_name); + + SendChildren(model_->GetRoot()); +} + +void CookiesTreeModelAdapter::TreeNodesAdded(ui::TreeModel* model, + ui::TreeModelNode* parent, + int start, + int count) { + // Skip if there is a batch update in progress. + if (batch_update_) + return; + + CookieTreeNode* parent_node = model_->AsNode(parent); + + StringValue tree_id(tree_id_); + scoped_ptr<Value> parend_id(GetTreeNodeId(parent_node)); + FundamentalValue start_value(start); + ListValue children; + cookies_tree_model_util::GetChildNodeList(parent_node, start, count, + &children); + web_ui_->CallJavascriptFunction("ui.CookiesTree.onTreeItemAdded", + tree_id, *parend_id.get(), start_value, children); +} + +void CookiesTreeModelAdapter::TreeNodesRemoved(ui::TreeModel* model, + ui::TreeModelNode* parent, + int start, + int count) { + // Skip if there is a batch update in progress. + if (batch_update_) + return; + + StringValue tree_id(tree_id_); + scoped_ptr<Value> parend_id(GetTreeNodeId(model_->AsNode(parent))); + FundamentalValue start_value(start); + FundamentalValue count_value(count); + web_ui_->CallJavascriptFunction("ui.CookiesTree.onTreeItemRemoved", + tree_id, *parend_id.get(), start_value, count_value); +} + +void CookiesTreeModelAdapter::TreeModelBeginBatch(CookiesTreeModel* model) { + DCHECK(!batch_update_); // There should be no nested batch begin. + batch_update_ = true; +} + +void CookiesTreeModelAdapter::TreeModelEndBatch(CookiesTreeModel* model) { + DCHECK(batch_update_); + batch_update_ = false; + + SendChildren(model_->GetRoot()); +} + +void CookiesTreeModelAdapter::RequestChildren(const ListValue* args) { + std::string node_path; + CHECK(args->GetString(0, &node_path)); + + CookieTreeNode* node = cookies_tree_model_util::GetTreeNodeFromPath( + model_->GetRoot(), node_path); + if (node) + SendChildren(node); +} + +void CookiesTreeModelAdapter::SendChildren(CookieTreeNode* parent) { + StringValue tree_id(tree_id_); + scoped_ptr<Value> parend_id(GetTreeNodeId(model_->AsNode(parent))); + ListValue children; + cookies_tree_model_util::GetChildNodeList(parent, 0, parent->child_count(), + &children); + web_ui_->CallJavascriptFunction("ui.CookiesTree.setChildren", + tree_id, *parend_id.get(), children); +} + +Value* CookiesTreeModelAdapter::GetTreeNodeId(CookieTreeNode* node) { + if (node == model_->GetRoot()) + return Value::CreateNullValue(); + + return Value::CreateStringValue( + cookies_tree_model_util::GetTreeNodeId(node)); +} diff --git a/chrome/browser/ui/webui/cookies_tree_model_adapter.h b/chrome/browser/ui/webui/cookies_tree_model_adapter.h new file mode 100644 index 0000000..6bb8311 --- /dev/null +++ b/chrome/browser/ui/webui/cookies_tree_model_adapter.h @@ -0,0 +1,71 @@ +// Copyright (c) 2011 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_COOKIES_TREE_MODEL_ADAPTER_H_ +#define CHROME_BROWSER_UI_WEBUI_COOKIES_TREE_MODEL_ADAPTER_H_ +#pragma once + +#include "chrome/browser/cookies_tree_model.h" + +class ListValue; +class Value; +class WebUI; + +// CookiesTreeModelAdapter binds a CookiesTreeModel with a JS tree. It observes +// tree model changes and forwards them to JS tree. It also provides a +// a callback for JS tree to load children of a specific node. +class CookiesTreeModelAdapter : public CookiesTreeModel::Observer { + public: + CookiesTreeModelAdapter(); + virtual ~CookiesTreeModelAdapter(); + + // Initializes with given WebUI. + void Init(WebUI* web_ui); + + // Sets up the bindings between js tree and |model|. + // Note that this class does not take ownership of the model. + void Bind(const std::string& tree_id, CookiesTreeModel* model); + + private: + // CookiesTreeModel::Observer implementation. + virtual void TreeNodesAdded(ui::TreeModel* model, + ui::TreeModelNode* parent, + int start, + int count); + virtual void TreeNodesRemoved(ui::TreeModel* model, + ui::TreeModelNode* parent, + int start, + int count); + virtual void TreeNodeChanged(ui::TreeModel* model, ui::TreeModelNode* node) {} + virtual void TreeModelBeginBatch(CookiesTreeModel* model); + virtual void TreeModelEndBatch(CookiesTreeModel* model); + + // JS callback that gets the tree node using the tree path info in |args| and + // call SendChildren to pass back children nodes data to WebUI. + void RequestChildren(const ListValue* args); + + // Get children nodes data and pass it to 'CookiesTree.loadChildren' to + // update the WebUI. + void SendChildren(CookieTreeNode* parent); + + // Helper function to get a Value* representing id of |node|. + // Caller needs to free the returned Value. + Value* GetTreeNodeId(CookieTreeNode* node); + + // Hosting WebUI of the js tree. + WebUI* web_ui_; + + // Id of JS tree that is managed by this handler. + std::string tree_id_; + + // The Cookies Tree model. Note that we are not owning the model. + CookiesTreeModel* model_; + + // Flag to indicate whether there is a batch update in progress. + bool batch_update_; + + DISALLOW_COPY_AND_ASSIGN(CookiesTreeModelAdapter); +}; + +#endif // CHROME_BROWSER_UI_WEBUI_COOKIES_TREE_MODEL_ADAPTER_H_ diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi index b2f822c..849ff3c 100644 --- a/chrome/chrome_browser.gypi +++ b/chrome/chrome_browser.gypi @@ -3196,8 +3196,12 @@ 'browser/ui/webui/chrome_url_data_manager_backend.h', 'browser/ui/webui/chrome_url_data_manager.cc', 'browser/ui/webui/chrome_url_data_manager.h', + 'browser/ui/webui/collected_cookies_ui_delegate.cc', + 'browser/ui/webui/collected_cookies_ui_delegate.h', 'browser/ui/webui/constrained_html_ui.cc', 'browser/ui/webui/constrained_html_ui.h', + 'browser/ui/webui/cookies_tree_model_adapter.cc', + 'browser/ui/webui/cookies_tree_model_adapter.h', 'browser/ui/webui/cookies_tree_model_util.cc', 'browser/ui/webui/cookies_tree_model_util.h', 'browser/ui/webui/crashes_ui.cc', @@ -3392,6 +3396,10 @@ ['exclude', 'browser/policy/device_policy_identity_strategy.h'], ['exclude', 'browser/renderer_host/offline_resource_handler.cc'], ['exclude', 'browser/renderer_host/offline_resource_handler.h'], + ['exclude', 'browser/ui/webui/collected_cookies_ui_delegate.cc'], + ['exclude', 'browser/ui/webui/collected_cookies_ui_delegate.h'], + ['exclude', 'browser/ui/webui/cookies_tree_model_adapter.cc'], + ['exclude', 'browser/ui/webui/cookies_tree_model_adapter.h'], ['exclude', 'browser/ui/webui/filebrowse_ui.cc'], ['exclude', 'browser/ui/webui/mediaplayer_ui.cc'], ['exclude', 'browser/ui/webui/slideshow_ui.cc'], diff --git a/chrome/common/url_constants.cc b/chrome/common/url_constants.cc index d57b89f..1387d51 100644 --- a/chrome/common/url_constants.cc +++ b/chrome/common/url_constants.cc @@ -80,6 +80,7 @@ const char kChromeUIAppLauncherURL[] = "chrome://newtab/#mode=app-launcher"; const char kChromeUIBookmarksURL[] = "chrome://bookmarks/"; const char kChromeUIBugReportURL[] = "chrome://bugreport/"; const char kChromeUIConflictsURL[] = "chrome://conflicts/"; +const char kChromeUICollectedCookiesURL[] = "chrome://collected-cookies/"; const char kChromeUIConstrainedHTMLTestURL[] = "chrome://constrained-test/"; const char kChromeUICrashesURL[] = "chrome://crashes/"; const char kChromeUIDevToolsURL[] = "chrome-devtools://devtools/"; @@ -117,6 +118,7 @@ const char kChromeUIBookmarksHost[] = "bookmarks"; const char kChromeUIBugReportHost[] = "bugreport"; const char kChromeUIConflictsHost[] = "conflicts"; const char kChromeUICrashesHost[] = "crashes"; +const char kChromeUICollectedCookiesHost[] = "collected-cookies"; const char kChromeUIDevToolsHost[] = "devtools"; const char kChromeUIDialogHost[] = "dialog"; const char kChromeUIDownloadsHost[] = "downloads"; diff --git a/chrome/common/url_constants.h b/chrome/common/url_constants.h index f9889d7..971a4df 100644 --- a/chrome/common/url_constants.h +++ b/chrome/common/url_constants.h @@ -72,6 +72,7 @@ extern const char kChromeUIAppLauncherURL[]; extern const char kChromeUIBookmarksURL[]; extern const char kChromeUIBugReportURL[]; extern const char kChromeUIConflictsURL[]; +extern const char kChromeUICollectedCookiesURL[]; extern const char kChromeUIConstrainedHTMLTestURL[]; extern const char kChromeUICrashesURL[]; extern const char kChromeUIDevToolsURL[]; @@ -110,6 +111,7 @@ extern const char kChromeUIBookmarksHost[]; extern const char kChromeUIBugReportHost[]; extern const char kChromeUIConflictsHost[]; extern const char kChromeUICrashesHost[]; +extern const char kChromeUICollectedCookiesHost[]; extern const char kChromeUIDevToolsHost[]; extern const char kChromeUIDialogHost[]; extern const char kChromeUIDownloadsHost[]; diff --git a/content/browser/webui/web_ui_factory.cc b/content/browser/webui/web_ui_factory.cc index 7468407..350d403 100644 --- a/content/browser/webui/web_ui_factory.cc +++ b/content/browser/webui/web_ui_factory.cc @@ -99,8 +99,10 @@ static WebUIFactoryFunction GetWebUIFactoryFunction(Profile* profile, if (url.SchemeIs(chrome::kGearsScheme)) return &NewWebUI<HtmlDialogUI>; - if (url.host() == chrome::kChromeUIDialogHost) + if (url.host() == chrome::kChromeUIDialogHost || + url.host() == chrome::kChromeUICollectedCookiesHost) { return &NewWebUI<ConstrainedHtmlUI>; + } ExtensionService* service = profile ? profile->GetExtensionService() : NULL; if (service && service->ExtensionBindingsAllowed(url)) |