diff options
author | mattm@chromium.org <mattm@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-08-24 01:11:41 +0000 |
---|---|---|
committer | mattm@chromium.org <mattm@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-08-24 01:11:41 +0000 |
commit | 214b81d70ec2a3eb09e381f7f306c651affd918b (patch) | |
tree | bdd252488d5e16af779121d70876376e67e9abbd /chrome/browser | |
parent | 083bac6bb70ed7d18c25d40112c0ae0431575a35 (diff) | |
download | chromium_src-214b81d70ec2a3eb09e381f7f306c651affd918b.zip chromium_src-214b81d70ec2a3eb09e381f7f306c651affd918b.tar.gz chromium_src-214b81d70ec2a3eb09e381f7f306c651affd918b.tar.bz2 |
Revert 97955 - First pass on intents options UI.
Copies the cookies view handler for intents.
Add pass-throughs to grit for flag.
Optionalize intents options page JS/CSS.
Fix up data model to read title. Working test.
R=jhawkins@chromium.org
BUG=None
TEST=*Intents*
Review URL: http://codereview.chromium.org/7624012
TBR=gbillock@chromium.org
Review URL: http://codereview.chromium.org/7717016
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@97966 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser')
17 files changed, 27 insertions, 1754 deletions
diff --git a/chrome/browser/intents/web_intents_registry.h b/chrome/browser/intents/web_intents_registry.h index 4b0f646..f5d724a 100644 --- a/chrome/browser/intents/web_intents_registry.h +++ b/chrome/browser/intents/web_intents_registry.h @@ -55,7 +55,6 @@ class WebIntentsRegistry // WebIntentsRegistry. friend class WebIntentsRegistryFactory; friend class WebIntentsRegistryTest; - friend class IntentsModelTest; WebIntentsRegistry(); virtual ~WebIntentsRegistry(); diff --git a/chrome/browser/intents/web_intents_registry_factory.h b/chrome/browser/intents/web_intents_registry_factory.h index 05ea36b8..4827097 100644 --- a/chrome/browser/intents/web_intents_registry_factory.h +++ b/chrome/browser/intents/web_intents_registry_factory.h @@ -18,7 +18,7 @@ class WebIntentsRegistry; class WebIntentsRegistryFactory : public ProfileKeyedServiceFactory { public: // Returns the WebIntentsRegistry that provides intent registration for - // |profile|. Ownership stays with this factory object. + // |profile|. static WebIntentsRegistry* GetForProfile(Profile* profile); // Returns the singleton instance of the WebIntentsRegistryFactory. diff --git a/chrome/browser/resources/options/content_settings.html b/chrome/browser/resources/options/content_settings.html index 9579633..ea1fb11 100644 --- a/chrome/browser/resources/options/content_settings.html +++ b/chrome/browser/resources/options/content_settings.html @@ -212,34 +212,30 @@ </div> </section> <!-- Intent registration filter tab contents --> - <if expr="pp_ifdef('enable_web_intents')"> - <section id="intents-section"> + <section id="intent-filter"> <h3 i18n-content="intentsTabLabel" class="content-settings-header"></h3> - <div> - <div class="radio"> - <label> - <input type="radio" name="intents" value="allow"> - <span i18n-content="intentsAllow"></span> - </label> - </div> - <div class="radio"> - <label> - <input type="radio" name="intents" value="ask"> - <span i18n-content="intentsAsk"></span> - </label> - </div> - <div class="radio"> - <label> - <input type="radio" name="intents" value="block"> - <span i18n-content="intentsBlock"></span> - </label> - </div> - <button class="exceptions-list-button" contentType="intents" - i18n-content="manage_exceptions"></button> - <button id="manage-intents-button" contentType="intents" - i18n-content="manageIntents"></button> + <div> + <div class="radio"> + <label> + <input type="radio" name="intents" value="allow"> + <span i18n-content="intentsAllow"></span> + </label> </div> - </section> - </if> + <div class="radio"> + <label> + <input type="radio" name="intents" value="ask"> + <span i18n-content="intentsAsk"></span> + </label> + </div> + <div class="radio"> + <label> + <input type="radio" name="intents" value="block"> + <span i18n-content="intentsBlock"></span> + </label> + </div> + <button class="exceptions-list-button" contentType="intents" + i18n-content="manage_exceptions"></button> + </div> + </section> </div> </div> diff --git a/chrome/browser/resources/options/content_settings.js b/chrome/browser/resources/options/content_settings.js index e8f5e52..08c6015 100644 --- a/chrome/browser/resources/options/content_settings.js +++ b/chrome/browser/resources/options/content_settings.js @@ -45,20 +45,14 @@ cr.define('options', function() { }; } - var manageHandlersButton = $('manage-handlers-button'); + var manageHandlersButton = + this.pageDiv.querySelector('#manage-handlers-button'); if (manageHandlersButton) { manageHandlersButton.onclick = function(event) { OptionsPage.navigateToPage('handlers'); }; } - var manageIntentsButton = $('manage-intents-button'); - if (manageIntentsButton) { - manageIntentsButton.onclick = function(event) { - OptionsPage.navigateToPage('intents'); - }; - } - // Cookies filter page --------------------------------------------------- $('show-cookies-button').onclick = function(event) { chrome.send('coreOptionsUserMetricsAction', ['Options_ShowCookies']); @@ -69,7 +63,7 @@ cr.define('options', function() { $('click_to_play').hidden = true; if (!templateData.enable_web_intents) - $('intent-section').hidden = true; + $('intent-filter').hidden = true; }, }; diff --git a/chrome/browser/resources/options/intents_list.js b/chrome/browser/resources/options/intents_list.js deleted file mode 100644 index d4f3fdd..0000000 --- a/chrome/browser/resources/options/intents_list.js +++ /dev/null @@ -1,715 +0,0 @@ -// 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. - -// TODO(gbillock): refactor this together with CookiesList once we have -// a better sense from UX design what it'll look like and so what'll be shared. -cr.define('options', function() { - const DeletableItemList = options.DeletableItemList; - const DeletableItem = options.DeletableItem; - const ArrayDataModel = cr.ui.ArrayDataModel; - const ListSingleSelectionModel = cr.ui.ListSingleSelectionModel; - const localStrings = new LocalStrings(); - - /** - * Returns the item's height, like offsetHeight but such that it works better - * when the page is zoomed. See the similar calculation in @{code cr.ui.List}. - * This version also accounts for the animation done in this file. - * @param {Element} item The item to get the height of. - * @return {number} The height of the item, calculated with zooming in mind. - */ - function getItemHeight(item) { - var height = item.style.height; - // Use the fixed animation target height if set, in case the element is - // currently being animated and we'd get an intermediate height below. - if (height && height.substr(-2) == 'px') - return parseInt(height.substr(0, height.length - 2)); - return item.getBoundingClientRect().height; - } - - // Map of parent pathIDs to node objects. - var parentLookup = {}; - - // Pending requests for child information. - var lookupRequests = {}; - - /** - * Creates a new list item for intent service data. Note that these are - * created and destroyed lazily as they scroll into and out of view, - * so they must be stateless. We cache the expanded item in - * @{code IntentsList} though, so it can keep state. - * (Mostly just which item is selected.) - * - * @param {Object} origin Data used to create an intents list item. - * @param {IntentsList} list The list that will contain this item. - * @constructor - * @extends {DeletableItem} - */ - function IntentsListItem(origin, list) { - var listItem = new DeletableItem(null); - listItem.__proto__ = IntentsListItem.prototype; - - listItem.origin = origin; - listItem.list = list; - listItem.decorate(); - - // This hooks up updateOrigin() to the list item, makes the top-level - // tree nodes (i.e., origins) register their IDs in parentLookup, and - // causes them to request their children if they have none. Note that we - // have special logic in the setter for the parent property to make sure - // that we can still garbage collect list items when they scroll out of - // view, even though it appears that we keep a direct reference. - if (origin) { - origin.parent = listItem; - origin.updateOrigin(); - } - - return listItem; - } - - IntentsListItem.prototype = { - __proto__: DeletableItem.prototype, - - /** @inheritDoc */ - decorate: function() { - this.siteChild = this.ownerDocument.createElement('div'); - this.siteChild.className = 'intents-site'; - this.dataChild = this.ownerDocument.createElement('div'); - this.dataChild.className = 'intents-data'; - this.itemsChild = this.ownerDocument.createElement('div'); - this.itemsChild.className = 'intents-items'; - this.infoChild = this.ownerDocument.createElement('div'); - this.infoChild.className = 'intents-details'; - this.infoChild.hidden = true; - var remove = this.ownerDocument.createElement('button'); - remove.textContent = localStrings.getString('removeIntent'); - remove.onclick = this.removeIntent_.bind(this); - this.infoChild.appendChild(remove); - var content = this.contentElement; - content.appendChild(this.siteChild); - content.appendChild(this.dataChild); - content.appendChild(this.itemsChild); - this.itemsChild.appendChild(this.infoChild); - if (this.origin && this.origin.data) { - this.siteChild.textContent = this.origin.data.site; - this.siteChild.setAttribute('title', this.origin.data.site); - } - this.itemList_ = []; - }, - - /** @type {boolean} */ - get expanded() { - return this.expanded_; - }, - set expanded(expanded) { - if (this.expanded_ == expanded) - return; - this.expanded_ = expanded; - if (expanded) { - var oldExpanded = this.list.expandedItem; - this.list.expandedItem = this; - this.updateItems_(); - if (oldExpanded) - oldExpanded.expanded = false; - this.classList.add('show-items'); - this.dataChild.hidden = true; - } else { - if (this.list.expandedItem == this) { - this.list.leadItemHeight = 0; - this.list.expandedItem = null; - } - this.style.height = ''; - this.itemsChild.style.height = ''; - this.classList.remove('show-items'); - this.dataChild.hidden = false; - } - }, - - /** - * The callback for the "remove" button shown when an item is selected. - * Requests that the currently selected intent service be removed. - * @private - */ - removeIntent_: function() { - if (this.selectedIndex_ >= 0) { - var item = this.itemList_[this.selectedIndex_]; - if (item && item.node) - chrome.send('removeIntent', [item.node.pathId]); - } - }, - - /** - * Disable animation within this intents list item, in preparation for - * making changes that will need to be animated. Makes it possible to - * measure the contents without displaying them, to set animation targets. - * @private - */ - disableAnimation_: function() { - this.itemsHeight_ = getItemHeight(this.itemsChild); - this.classList.add('measure-items'); - }, - - /** - * Enable animation after changing the contents of this intents list item. - * See @{code disableAnimation_}. - * @private - */ - enableAnimation_: function() { - if (!this.classList.contains('measure-items')) - this.disableAnimation_(); - this.itemsChild.style.height = ''; - // This will force relayout in order to calculate the new heights. - var itemsHeight = getItemHeight(this.itemsChild); - var fixedHeight = getItemHeight(this) + itemsHeight - this.itemsHeight_; - this.itemsChild.style.height = this.itemsHeight_ + 'px'; - // Force relayout before enabling animation, so that if we have - // changed things since the last layout, they will not be animated - // during subsequent layouts. - this.itemsChild.offsetHeight; - this.classList.remove('measure-items'); - this.itemsChild.style.height = itemsHeight + 'px'; - this.style.height = fixedHeight + 'px'; - if (this.expanded) - this.list.leadItemHeight = fixedHeight; - }, - - /** - * Updates the origin summary to reflect changes in its items. - * Both IntentsListItem and IntentsTreeNode implement this API. - * This implementation scans the descendants to update the text. - */ - updateOrigin: function() { - console.log('IntentsListItem.updateOrigin'); - var text = ''; - for (var i = 0; i < this.origin.children.length; ++i) { - if (text.length > 0) - text += ', ' + this.origin.children[i].data.action; - else - text = this.origin.children[i].data.action; - } - this.dataChild.textContent = text; - - if (this.expanded) - this.updateItems_(); - }, - - /** - * Updates the items section to reflect changes, animating to the new state. - * Removes existing contents and calls @{code IntentsTreeNode.createItems}. - * @private - */ - updateItems_: function() { - this.disableAnimation_(); - this.itemsChild.textContent = ''; - this.infoChild.hidden = true; - this.selectedIndex_ = -1; - this.itemList_ = []; - if (this.origin) - this.origin.createItems(this); - this.itemsChild.appendChild(this.infoChild); - this.enableAnimation_(); - }, - - /** - * Append a new intents node "bubble" to this list item. - * @param {IntentsTreeNode} node The intents node to add a bubble for. - * @param {Element} div The DOM element for the bubble itself. - * @return {number} The index the bubble was added at. - */ - appendItem: function(node, div) { - this.itemList_.push({node: node, div: div}); - this.itemsChild.appendChild(div); - return this.itemList_.length - 1; - }, - - /** - * The currently selected intents node ("intents bubble") index. - * @type {number} - * @private - */ - selectedIndex_: -1, - - /** - * Get the currently selected intents node ("intents bubble") index. - * @type {number} - */ - get selectedIndex() { - return this.selectedIndex_; - }, - - /** - * Set the currently selected intents node ("intents bubble") index to - * @{code itemIndex}, unselecting any previously selected node first. - * @param {number} itemIndex The index to set as the selected index. - * TODO: KILL THIS - */ - set selectedIndex(itemIndex) { - // Get the list index up front before we change anything. - var index = this.list.getIndexOfListItem(this); - // Unselect any previously selected item. - if (this.selectedIndex_ >= 0) { - var item = this.itemList_[this.selectedIndex_]; - if (item && item.div) - item.div.removeAttribute('selected'); - } - // Special case: decrementing -1 wraps around to the end of the list. - if (itemIndex == -2) - itemIndex = this.itemList_.length - 1; - // Check if we're going out of bounds and hide the item details. - if (itemIndex < 0 || itemIndex >= this.itemList_.length) { - this.selectedIndex_ = -1; - this.disableAnimation_(); - this.infoChild.hidden = true; - this.enableAnimation_(); - return; - } - // Set the new selected item and show the item details for it. - this.selectedIndex_ = itemIndex; - this.itemList_[itemIndex].div.setAttribute('selected', ''); - this.disableAnimation_(); - this.infoChild.hidden = false; - this.enableAnimation_(); - // If we're near the bottom of the list this may cause the list item to go - // beyond the end of the visible area. Fix it after the animation is done. - var list = this.list; - window.setTimeout(function() { list.scrollIndexIntoView(index); }, 150); - }, - }; - - /** - * {@code IntentsTreeNode}s mirror the structure of the intents tree lazily, - * and contain all the actual data used to generate the - * {@code IntentsListItem}s. - * @param {Object} data The data object for this node. - * @constructor - */ - function IntentsTreeNode(data) { - this.data = data; - this.children = []; - } - - IntentsTreeNode.prototype = { - /** - * Insert an intents tree node at the given index. - * Both IntentsList and IntentsTreeNode implement this API. - * @param {Object} data The data object for the node to add. - * @param {number} index The index at which to insert the node. - */ - insertAt: function(data, index) { - console.log('IntentsTreeNode.insertAt adding ' + - JSON.stringify(data) + ' at ' + index); - var child = new IntentsTreeNode(data); - this.children.splice(index, 0, child); - child.parent = this; - this.updateOrigin(); - }, - - /** - * Remove an intents tree node from the given index. - * Both IntentsList and IntentsTreeNode implement this API. - * @param {number} index The index of the tree node to remove. - */ - remove: function(index) { - if (index < this.children.length) { - this.children.splice(index, 1); - this.updateOrigin(); - } - }, - - /** - * Clears all children. - * Both IntentsList and IntentsTreeNode implement this API. - * It is used by IntentsList.loadChildren(). - */ - clear: function() { - // We might leave some garbage in parentLookup for removed children. - // But that should be OK because parentLookup is cleared when we - // reload the tree. - this.children = []; - this.updateOrigin(); - }, - - /** - * The counter used by startBatchUpdates() and endBatchUpdates(). - * @type {number} - */ - batchCount_: 0, - - /** - * See cr.ui.List.startBatchUpdates(). - * Both IntentsList (via List) and IntentsTreeNode implement this API. - */ - startBatchUpdates: function() { - this.batchCount_++; - }, - - /** - * See cr.ui.List.endBatchUpdates(). - * Both IntentsList (via List) and IntentsTreeNode implement this API. - */ - endBatchUpdates: function() { - if (!--this.batchCount_) - this.updateOrigin(); - }, - - /** - * Requests updating the origin summary to reflect changes in this item. - * Both IntentsListItem and IntentsTreeNode implement this API. - */ - updateOrigin: function() { - if (!this.batchCount_ && this.parent) - this.parent.updateOrigin(); - }, - - /** - * Create the intents services rows for this node. - * Append the rows to @{code item}. - * @param {IntentsListItem} item The intents list item to create items in. - */ - createItems: function(item) { - if (this.children.length > 0) { - for (var i = 0; i < this.children.length; ++i) - this.children[i].createItems(item); - } else if (this.data && !this.data.hasChildren) { - var div = item.ownerDocument.createElement('div'); - div.className = 'intents-item'; - // Help out screen readers and such: this is a clickable thing. - div.setAttribute('role', 'button'); - - var divAction = item.ownerDocument.createElement('div'); - divAction.className = 'intents-item-action'; - divAction.textContent = this.data.action; - div.appendChild(divAction); - - var divTypes = item.ownerDocument.createElement('div'); - divTypes.className = 'intents-item-types'; - var text = ""; - for (var i = 0; i < this.data.types.length; ++i) { - if (text != "") - text += ", "; - text += this.data.types[i]; - } - divTypes.textContent = text; - div.appendChild(divTypes); - - var divUrl = item.ownerDocument.createElement('div'); - divUrl.className = 'intents-item-url'; - divUrl.textContent = this.data.url; - div.appendChild(divUrl); - - var index = item.appendItem(this, div); - div.onclick = function() { - if (item.selectedIndex == index) - item.selectedIndex = -1; - else - item.selectedIndex = index; - }; - } - }, - - /** - * The parent of this intents tree node. - * @type {?IntentsTreeNode|IntentsListItem} - */ - get parent(parent) { - // See below for an explanation of this special case. - if (typeof this.parent_ == 'number') - return this.list_.getListItemByIndex(this.parent_); - return this.parent_; - }, - set parent(parent) { - if (parent == this.parent) - return; - - if (parent instanceof IntentsListItem) { - // If the parent is to be a IntentsListItem, then we keep the reference - // to it by its containing list and list index, rather than directly. - // This allows the list items to be garbage collected when they scroll - // out of view (except the expanded item, which we cache). This is - // transparent except in the setter and getter, where we handle it. - this.parent_ = parent.listIndex; - this.list_ = parent.list; - parent.addEventListener('listIndexChange', - this.parentIndexChanged_.bind(this)); - } else { - this.parent_ = parent; - } - - - if (parent) - parentLookup[this.pathId] = this; - else - delete parentLookup[this.pathId]; - - if (this.data && this.data.hasChildren && - !this.children.length && !lookupRequests[this.pathId]) { - console.log('SENDING loadIntents'); - lookupRequests[this.pathId] = true; - chrome.send('loadIntents', [this.pathId]); - } - }, - - /** - * Called when the parent is a IntentsListItem whose index has changed. - * See the code above that avoids keeping a direct reference to - * IntentsListItem parents, to allow them to be garbage collected. - * @private - */ - parentIndexChanged_: function(event) { - if (typeof this.parent_ == 'number') { - this.parent_ = event.newValue; - // We set a timeout to update the origin, rather than doing it right - // away, because this callback may occur while the list items are - // being repopulated following a scroll event. Calling updateOrigin() - // immediately could trigger relayout that would reset the scroll - // position within the list, among other things. - window.setTimeout(this.updateOrigin.bind(this), 0); - } - }, - - /** - * The intents tree path id. - * @type {string} - */ - get pathId() { - var parent = this.parent; - if (parent && parent instanceof IntentsTreeNode) - return parent.pathId + ',' + this.data.action; - return this.data.site; - }, - }; - - /** - * Creates a new intents list. - * @param {Object=} opt_propertyBag Optional properties. - * @constructor - * @extends {DeletableItemList} - */ - var IntentsList = cr.ui.define('list'); - - IntentsList.prototype = { - __proto__: DeletableItemList.prototype, - - /** @inheritDoc */ - decorate: function() { - DeletableItemList.prototype.decorate.call(this); - this.classList.add('intents-list'); - this.data_ = []; - this.dataModel = new ArrayDataModel(this.data_); - this.addEventListener('keydown', this.handleKeyLeftRight_.bind(this)); - var sm = new ListSingleSelectionModel(); - sm.addEventListener('change', this.cookieSelectionChange_.bind(this)); - sm.addEventListener('leadIndexChange', this.cookieLeadChange_.bind(this)); - this.selectionModel = sm; - }, - - /** - * Handles key down events and looks for left and right arrows, then - * dispatches to the currently expanded item, if any. - * @param {Event} e The keydown event. - * @private - */ - handleKeyLeftRight_: function(e) { - var id = e.keyIdentifier; - if ((id == 'Left' || id == 'Right') && this.expandedItem) { - var cs = this.ownerDocument.defaultView.getComputedStyle(this); - var rtl = cs.direction == 'rtl'; - if ((!rtl && id == 'Left') || (rtl && id == 'Right')) - this.expandedItem.selectedIndex--; - else - this.expandedItem.selectedIndex++; - this.scrollIndexIntoView(this.expandedItem.listIndex); - // Prevent the page itself from scrolling. - e.preventDefault(); - } - }, - - /** - * Called on selection model selection changes. - * @param {Event} ce The selection change event. - * @private - */ - cookieSelectionChange_: function(ce) { - ce.changes.forEach(function(change) { - var listItem = this.getListItemByIndex(change.index); - if (listItem) { - if (!change.selected) { - // We set a timeout here, rather than setting the item unexpanded - // immediately, so that if another item gets set expanded right - // away, it will be expanded before this item is unexpanded. It - // will notice that, and unexpand this item in sync with its own - // expansion. Later, this callback will end up having no effect. - window.setTimeout(function() { - if (!listItem.selected || !listItem.lead) - listItem.expanded = false; - }, 0); - } else if (listItem.lead) { - listItem.expanded = true; - } - } - }, this); - }, - - /** - * Called on selection model lead changes. - * @param {Event} pe The lead change event. - * @private - */ - cookieLeadChange_: function(pe) { - if (pe.oldValue != -1) { - var listItem = this.getListItemByIndex(pe.oldValue); - if (listItem) { - // See cookieSelectionChange_ above for why we use a timeout here. - window.setTimeout(function() { - if (!listItem.lead || !listItem.selected) - listItem.expanded = false; - }, 0); - } - } - if (pe.newValue != -1) { - var listItem = this.getListItemByIndex(pe.newValue); - if (listItem && listItem.selected) - listItem.expanded = true; - } - }, - - /** - * The currently expanded item. Used by IntentsListItem above. - * @type {?IntentsListItem} - */ - expandedItem: null, - - // from cr.ui.List - /** @inheritDoc */ - createItem: function(data) { - // We use the cached expanded item in order to allow it to maintain some - // state (like its fixed height, and which bubble is selected). - if (this.expandedItem && this.expandedItem.origin == data) - return this.expandedItem; - return new IntentsListItem(data, this); - }, - - // from options.DeletableItemList - /** @inheritDoc */ - deleteItemAtIndex: function(index) { - var item = this.data_[index]; - if (item) { - var pathId = item.pathId; - if (pathId) - chrome.send('removeIntent', [pathId]); - } - }, - - /** - * Insert an intents tree node at the given index. - * Both IntentsList and IntentsTreeNode implement this API. - * @param {Object} data The data object for the node to add. - * @param {number} index The index at which to insert the node. - */ - insertAt: function(data, index) { - this.dataModel.splice(index, 0, new IntentsTreeNode(data)); - }, - - /** - * Remove an intents tree node from the given index. - * Both IntentsList and IntentsTreeNode implement this API. - * @param {number} index The index of the tree node to remove. - */ - remove: function(index) { - if (index < this.data_.length) - this.dataModel.splice(index, 1); - }, - - /** - * Clears the list. - * Both IntentsList and IntentsTreeNode implement this API. - * It is used by IntentsList.loadChildren(). - */ - clear: function() { - parentLookup = {}; - this.data_ = []; - this.dataModel = new ArrayDataModel(this.data_); - this.redraw(); - }, - - /** - * Add tree nodes by given parent. - * Note: this method will be O(n^2) in the general case. Use it only to - * populate an empty parent or to insert single nodes to avoid this. - * @param {Object} parent The parent node. - * @param {number} start Start index of where to insert nodes. - * @param {Array} nodesData Nodes data array. - * @private - */ - addByParent_: function(parent, start, nodesData) { - if (!parent) - return; - - parent.startBatchUpdates(); - for (var i = 0; i < nodesData.length; ++i) - parent.insertAt(nodesData[i], start + i); - parent.endBatchUpdates(); - - cr.dispatchSimpleEvent(this, 'change'); - }, - - /** - * Add tree nodes by parent id. - * This is used by intents_view.js. - * Note: this method will be O(n^2) in the general case. Use it only to - * populate an empty parent or to insert single nodes to avoid this. - * @param {string} parentId Id of the parent node. - * @param {number} start Start index of where to insert nodes. - * @param {Array} nodesData Nodes data array. - */ - addByParentId: function(parentId, start, nodesData) { - var parent = parentId ? parentLookup[parentId] : this; - this.addByParent_(parent, start, nodesData); - }, - - /** - * Removes tree nodes by parent id. - * This is used by intents_view.js. - * @param {string} parentId Id of the parent node. - * @param {number} start Start index of nodes to remove. - * @param {number} count Number of nodes to remove. - */ - removeByParentId: function(parentId, start, count) { - var parent = parentId ? parentLookup[parentId] : this; - if (!parent) - return; - - parent.startBatchUpdates(); - while (count-- > 0) - parent.remove(start); - parent.endBatchUpdates(); - - cr.dispatchSimpleEvent(this, 'change'); - }, - - /** - * Loads the immediate children of given parent node. - * This is used by intents_view.js. - * @param {string} parentId Id of the parent node. - * @param {Array} children The immediate children of parent node. - */ - loadChildren: function(parentId, children) { - console.log('Loading intents view: ' + - parentId + ' ' + JSON.stringify(children)); - if (parentId) - delete lookupRequests[parentId]; - var parent = parentId ? parentLookup[parentId] : this; - if (!parent) - return; - - parent.startBatchUpdates(); - parent.clear(); - this.addByParent_(parent, 0, children); - parent.endBatchUpdates(); - }, - }; - - return { - IntentsList: IntentsList - }; -}); diff --git a/chrome/browser/resources/options/intents_view.css b/chrome/browser/resources/options/intents_view.css deleted file mode 100644 index 84c274d..0000000 --- a/chrome/browser/resources/options/intents_view.css +++ /dev/null @@ -1,181 +0,0 @@ -/* -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. -*/ - -/* Styles for the intents list elements in intents_view.html. */ - -#intents-column-headers { - position: relative; - width: 100%; -} - -#intents-column-headers h3 { - font-size: 105%; - font-weight: bold; - margin: 10px 0; -} - -/* Notice the width and padding for these columns match up with those below. */ -#intents-site-column { - display: inline-block; - font-weight: bold; - width: 11em; -} - -#intents-data-column { - -webkit-padding-start: 7px; - display: inline-block; - font-weight: bold; -} - -#intents-list { - border: 1px solid #d9d9d9; - margin: 0; -} - -/* Enable animating the height of items. */ -list.intents-list .deletable-item { - -webkit-transition: height .15s ease-in-out; -} - -/* Disable webkit-box display. */ -list.intents-list .deletable-item > :first-child { - display: block; -} - -/* Force the X for deleting an origin to stay at the top. */ -list.intents-list > .deletable-item > .close-button { - position: absolute; - right: 2px; - top: 8px; -} - -html[dir=rtl] list.intents-list > .deletable-item > .close-button { - left: 2px; - right: auto; -} - -/* Styles for the site (aka origin) and its summary. */ - -.intents-site { - /* Notice that the width, margin, and padding match up with those above. */ - -webkit-margin-end: 2px; - -webkit-padding-start: 5px; - display: inline-block; - overflow: hidden; - text-overflow: ellipsis; - width: 11em; -} - -list.intents-list > .deletable-item[selected] .intents-site { - -webkit-user-select: text; -} - -.intents-data { - display: inline-block; -} - -list.intents-list > .deletable-item[selected] .intents-data { - -webkit-user-select: text; -} - -.intents-items { - /* Notice that the margin and padding match up with those above. */ - -webkit-margin-start: 11em; - -webkit-padding-start: 7px; - -webkit-transition: .15s ease-in-out; - display: table; - height: 0; - opacity: 0; - /* Make the intents items wrap correctly. */ - white-space: normal; -} - -.measure-items .intents-items { - -webkit-transition: none; - height: auto; - visibility: hidden; -} - -.show-items .intents-items { - opacity: 1; -} - -.intents-items .intents-item { - -webkit-box-orient: horizontal; - -webkit-box-pack: start; - background: #e0e9f5; - border: 1px solid #8392ae; - display: table-row; - font-size: 85%; - height: auto; - margin: 2px 4px 2px 0; - overflow: hidden; - padding: 0 3px; - text-align: center; - text-overflow: ellipsis; -} - -.intents-item .intents-item-action { - display: table-cell; - padding: 2px 5px; -} - -.intents-item .intents-item-types { - display: table-cell; - padding: 2px 5px; - overflow: hidden; -} - -.intents-item .intents-item-url { - display: table-cell; - padding: 2px 5px; - overflow: hidden; - text-overflow: ellipsis; -} - -.intents-items .intents-item:hover { - background: #eef3f9; - border-color: #647187; -} - -.intents-items .intents-item[selected] { - background: #f5f8f8; - border-color: #b2b2b2; -} - -.intents-items .intents-item[selected]:hover { - background: #f5f8f8; - border-color: #647187; -} - -/* Styles for the intents details box. */ - -.intents-details { - background: #f5f8f8; - border-radius: 5px; - border: 1px solid #b2b2b2; - margin-top: 2px; - padding: 5px; -} - -list.intents-list > .deletable-item[selected] .intents-details { - -webkit-user-select: text; -} - -.intents-details-table { - table-layout: fixed; - width: 100%; -} - -.intents-details-label { - vertical-align: top; - white-space: pre; - width: 10em; -} - -.intents-details-value { - word-wrap: break-word; -} diff --git a/chrome/browser/resources/options/intents_view.html b/chrome/browser/resources/options/intents_view.html deleted file mode 100644 index 6803c23..0000000 --- a/chrome/browser/resources/options/intents_view.html +++ /dev/null @@ -1,12 +0,0 @@ -<div id="intents-view-page" class="page" hidden> - <h1 i18n-content="intentsViewPage"></h1> - <div id="intents-column-headers"> - <div id="intents-site-column"> - <h3 i18n-content="intentsDomain"></h3> - </div> - <div id="intents-data-column"> - <h3 i18n-content="intentsServiceData"></h3> - </div> - </div> - <list id="intents-list"></list> -</div> diff --git a/chrome/browser/resources/options/intents_view.js b/chrome/browser/resources/options/intents_view.js deleted file mode 100644 index afc7d68..0000000 --- a/chrome/browser/resources/options/intents_view.js +++ /dev/null @@ -1,83 +0,0 @@ -// 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. - -cr.define('options', function() { - var OptionsPage = options.OptionsPage; - - ///////////////////////////////////////////////////////////////////////////// - // IntentsView class: - - /** - * Encapsulated handling of the Intents data page. - * @constructor - */ - function IntentsView(model) { - OptionsPage.call(this, 'intents', - templateData.intentsViewPageTabTitle, - 'intents-view-page'); - } - - cr.addSingletonGetter(IntentsView); - - IntentsView.prototype = { - __proto__: OptionsPage.prototype, - - initializePage: function() { - OptionsPage.prototype.initializePage.call(this); - - var intentsList = $('intents-list'); - options.IntentsList.decorate(intentsList); - window.addEventListener('resize', this.handleResize_.bind(this)); - - this.addEventListener('visibleChange', this.handleVisibleChange_); - }, - - initialized_: false, - - /** - * Handler for OptionsPage's visible property change event. - * @param {Event} e Property change event. - * @private - */ - handleVisibleChange_: function(e) { - if (!this.visible) - return; - - // Resize the intents list whenever the options page becomes visible. - this.handleResize_(null); - if (!this.initialized_) { - this.initialized_ = true; - chrome.send('loadIntents'); - } else { - $('intents-list').redraw(); - } - }, - - /** - * Handler for when the window changes size. Resizes the intents list to - * match the window height. - * @param {?Event} e Window resize event, or null if called directly. - * @private - */ - handleResize_: function(e) { - if (!this.visible) - return; - var intentsList = $('intents-list'); - // 25 pixels from the window bottom seems like a visually pleasing amount. - var height = window.innerHeight - intentsList.offsetTop - 25; - intentsList.style.height = height + 'px'; - }, - }; - - // IntentsViewHandler callbacks. - IntentsView.loadChildren = function(args) { - $('intents-list').loadChildren(args[0], args[1]); - }; - - // Export - return { - IntentsView: IntentsView - }; - -}); diff --git a/chrome/browser/resources/options/options.html b/chrome/browser/resources/options/options.html index de3754c..3fb7c74 100644 --- a/chrome/browser/resources/options/options.html +++ b/chrome/browser/resources/options/options.html @@ -29,9 +29,6 @@ <link rel="stylesheet" href="handler_options.css"> </if> <link rel="stylesheet" href="import_data_overlay.css"> -<if expr="pp_ifdef('enable_web_intents')"> - <link rel="stylesheet" href="intents_view.css"> -</if> <link rel="stylesheet" href="language_options.css"> <link rel="stylesheet" href="manage_profile_overlay.css"> <link rel="stylesheet" href="password_manager.css"> @@ -167,9 +164,6 @@ <if expr="pp_ifdef('enable_register_protocol_handler')"> <include src="handler_options.html"> </if> - <if expr="pp_ifdef('enable_web_intents')"> - <include src="intents_view.html"> - </if> <include src="content_settings_exceptions_area.html"> </div> </div> diff --git a/chrome/browser/resources/options/options.js b/chrome/browser/resources/options/options.js index 3e5c41b..de55f64 100644 --- a/chrome/browser/resources/options/options.js +++ b/chrome/browser/resources/options/options.js @@ -17,7 +17,6 @@ var CookiesView = options.CookiesView; var FontSettings = options.FontSettings; var HandlerOptions = options.HandlerOptions; var ImportDataOverlay = options.ImportDataOverlay; -var IntentsView = options.IntentsView; var InstantConfirmOverlay = options.InstantConfirmOverlay; var LanguageOptions = options.LanguageOptions; var OptionsPage = options.OptionsPage; @@ -121,11 +120,6 @@ function load() { ContentSettings.getInstance(), [$('manage-handlers-button')]); } - if (IntentsView && $('manage-intents-button')) { - OptionsPage.registerSubPage(IntentsView.getInstance(), - ContentSettings.getInstance(), - [$('manage-intents-button')]); - } OptionsPage.registerSubPage(FontSettings.getInstance(), AdvancedOptions.getInstance(), [$('fontSettingsCustomizeFontsButton')]); diff --git a/chrome/browser/resources/options/options_bundle.js b/chrome/browser/resources/options/options_bundle.js index 0b58a74..a181de9 100644 --- a/chrome/browser/resources/options/options_bundle.js +++ b/chrome/browser/resources/options/options_bundle.js @@ -68,10 +68,6 @@ </if> <include src="import_data_overlay.js"></include> <include src="instant_confirm_overlay.js"></include> -<if expr="pp_ifdef('enable_web_intents')"> - <include src="intents_list.js"></include> - <include src="intents_view.js"></include> -</if> <include src="language_add_language_overlay.js"></include> <include src="language_list.js"></include> <include src="language_options.js"></include> diff --git a/chrome/browser/ui/intents/intents_model.cc b/chrome/browser/ui/intents/intents_model.cc deleted file mode 100644 index 8114724..0000000 --- a/chrome/browser/ui/intents/intents_model.cc +++ /dev/null @@ -1,152 +0,0 @@ -// 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/intents/intents_model.h" -#include "base/string_split.h" -#include "base/string_util.h" -#include "base/stringprintf.h" -#include "base/utf_string_conversions.h" -#include "chrome/browser/intents/web_intents_registry.h" - -ServiceTreeNode::ServiceTreeNode(const string16& title) - : IntentsTreeNode(title, IntentsTreeNode::TYPE_SERVICE), - blocked_(false), - disabled_(false) {} - -ServiceTreeNode::~ServiceTreeNode() {} - -IntentsModel::IntentsModel(WebIntentsRegistry* intents_registry) - : ui::TreeNodeModel<IntentsTreeNode>(new IntentsTreeNode()), - intents_registry_(intents_registry), - batch_update_(0) { - LoadModel(); -} - -IntentsModel::~IntentsModel() {} - -void IntentsModel::AddIntentsTreeObserver(Observer* observer) { - intents_observer_list_.AddObserver(observer); - // Call super so that TreeNodeModel can notify, too. - ui::TreeNodeModel<IntentsTreeNode>::AddObserver(observer); -} - -void IntentsModel::RemoveIntentsTreeObserver(Observer* observer) { - intents_observer_list_.RemoveObserver(observer); - // Call super so that TreeNodeModel doesn't have dead pointers. - ui::TreeNodeModel<IntentsTreeNode>::RemoveObserver(observer); -} - -string16 IntentsModel::GetTreeNodeId(IntentsTreeNode* node) { - if (node->Type() == IntentsTreeNode::TYPE_ORIGIN) - return node->GetTitle(); - - // TODO(gbillock): handle TYPE_SERVICE when/if we ever want to do - // specific managing of them. - - return string16(); -} - -IntentsTreeNode* IntentsModel::GetTreeNode(std::string path_id) { - if (path_id.empty()) - return GetRoot(); - - std::vector<std::string> node_ids; - base::SplitString(path_id, ',', &node_ids); - - for (int i = 0; i < GetRoot()->child_count(); ++i) { - IntentsTreeNode* node = GetRoot()->GetChild(i); - if (UTF16ToUTF8(node->GetTitle()) == node_ids[0]) { - if (node_ids.size() == 1) - return node; - } - } - - // TODO: support service nodes? - return NULL; -} - -void IntentsModel::GetChildNodeList(IntentsTreeNode* parent, - int start, int count, - base::ListValue* nodes) { - for (int i = 0; i < count; ++i) { - base::DictionaryValue* dict = new base::DictionaryValue; - IntentsTreeNode* child = parent->GetChild(start + i); - GetIntentsTreeNodeDictionary(*child, dict); - nodes->Append(dict); - } -} - -void IntentsModel::GetIntentsTreeNodeDictionary(const IntentsTreeNode& node, - base::DictionaryValue* dict) { - if (node.Type() == IntentsTreeNode::TYPE_ROOT) { - return; - } - - if (node.Type() == IntentsTreeNode::TYPE_ORIGIN) { - dict->SetString("site", node.GetTitle()); - dict->SetBoolean("hasChildren", node.child_count() > 0); - return; - } - - if (node.Type() == IntentsTreeNode::TYPE_SERVICE) { - const ServiceTreeNode* snode = static_cast<const ServiceTreeNode*>(&node); - dict->SetString("site", snode->GetTitle()); - dict->SetString("name", snode->ServiceName()); - dict->SetString("url", snode->ServiceUrl()); - dict->SetString("icon", snode->IconUrl()); - dict->SetString("action", snode->Action()); - dict->Set("types", snode->Types().DeepCopy()); - dict->SetBoolean("blocked", snode->IsBlocked()); - dict->SetBoolean("disabled", snode->IsDisabled()); - return; - } -} - -void IntentsModel::LoadModel() { - NotifyObserverBeginBatch(); - intents_registry_->GetAllIntentProviders(this); -} - -void IntentsModel::OnIntentsQueryDone( - WebIntentsRegistry::QueryID query_id, - const std::vector<WebIntentData>& intents) { - for (size_t i = 0; i < intents.size(); ++i) { - // Eventually do some awesome sorting, grouping, clustering stuff here. - // For now, just stick it in the model flat. - IntentsTreeNode* n = new IntentsTreeNode(ASCIIToUTF16( - intents[i].service_url.host())); - ServiceTreeNode* ns = new ServiceTreeNode(ASCIIToUTF16( - intents[i].service_url.host())); - ns->SetServiceName(intents[i].title); - ns->SetServiceUrl(ASCIIToUTF16(intents[i].service_url.spec())); - GURL icon_url = intents[i].service_url.GetOrigin().Resolve("/favicon.ico"); - ns->SetIconUrl(ASCIIToUTF16(icon_url.spec())); - ns->SetAction(intents[i].action); - ns->AddType(intents[i].type); - // Won't generate a notification. OK for now as the next line will. - n->Add(ns, 0); - Add(GetRoot(), n, GetRoot()->child_count()); - } - - NotifyObserverEndBatch(); -} - -void IntentsModel::NotifyObserverBeginBatch() { - // Only notify the model once if we're batching in a nested manner. - if (batch_update_++ == 0) { - FOR_EACH_OBSERVER(Observer, - intents_observer_list_, - TreeModelBeginBatch(this)); - } -} - -void IntentsModel::NotifyObserverEndBatch() { - // Only notify the observers if this is the outermost call to EndBatch() if - // called in a nested manner. - if (--batch_update_ == 0) { - FOR_EACH_OBSERVER(Observer, - intents_observer_list_, - TreeModelEndBatch(this)); - } -} diff --git a/chrome/browser/ui/intents/intents_model.h b/chrome/browser/ui/intents/intents_model.h deleted file mode 100644 index 0221b7d..0000000 --- a/chrome/browser/ui/intents/intents_model.h +++ /dev/null @@ -1,133 +0,0 @@ -// 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_INTENTS_INTENTS_MODEL_H_ -#define CHROME_BROWSER_UI_INTENTS_INTENTS_MODEL_H_ -#pragma once - -#include "base/values.h" -#include "chrome/browser/intents/web_intents_registry.h" -#include "ui/base/models/tree_node_model.h" - -class WebIntentsRegistry; - -// The tree structure is a TYPE_ROOT node with title="", -// children are TYPE_ORIGIN nodes with title=origin, whose -// children are TYPE_SERVICE nodes with title=origin, and -// will be of type ServiceTreeNode with data on individual -// services. -class IntentsTreeNode : public ui::TreeNode<IntentsTreeNode> { - public: - IntentsTreeNode() - : ui::TreeNode<IntentsTreeNode>(string16()), - type_(TYPE_ROOT) {} - - explicit IntentsTreeNode(const string16& title) - : ui::TreeNode<IntentsTreeNode>(title), - type_(TYPE_ORIGIN) {} - - virtual ~IntentsTreeNode() {} - - enum NodeType { - TYPE_ROOT, - TYPE_ORIGIN, - TYPE_SERVICE, - }; - - NodeType Type() const { return type_; } - - protected: - IntentsTreeNode(const string16& title, NodeType type) - : ui::TreeNode<IntentsTreeNode>(title), - type_(type) {} - - private: - NodeType type_; -}; - -// Tree node representing particular services presented by an origin. -class ServiceTreeNode : public IntentsTreeNode { - public: - explicit ServiceTreeNode(const string16& title); - virtual ~ServiceTreeNode(); - - const string16& ServiceName() const { return service_name_; } - const string16& ServiceUrl() const { return service_url_; } - const string16& IconUrl() const { return icon_url_; } - const string16& Action() const { return action_; } - const base::ListValue& Types() const { return types_; } - bool IsBlocked() const { return blocked_; } - bool IsDisabled() const { return disabled_; } - - void SetServiceName(string16 name) { service_name_ = name; } - void SetServiceUrl(string16 url) { service_url_ = url; } - void SetIconUrl(string16 url) { icon_url_ = url; } - void SetAction(string16 action) { action_ = action; } - void AddType(string16 type) { types_.Append(Value::CreateStringValue(type)); } - void SetBlocked(bool blocked) { blocked_ = blocked; } - void SetDisabled(bool disabled) { disabled_ = disabled; } - - private: - string16 service_name_; - string16 icon_url_; - string16 service_url_; - string16 action_; - base::ListValue types_; - - // TODO(gbillock): these are kind of a placeholder for exceptions data. - bool blocked_; - bool disabled_; -}; - -// UI-backing tree model of the data in the WebIntentsRegistry. -class IntentsModel : public ui::TreeNodeModel<IntentsTreeNode>, - public WebIntentsRegistry::Consumer { - public: - // Because nodes are fetched in a background thread, they are not - // present at the time the Model is created. The Model then notifies its - // observers for every item added. - class Observer : public ui::TreeModelObserver { - public: - virtual void TreeModelBeginBatch(IntentsModel* model) {} - virtual void TreeModelEndBatch(IntentsModel* model) {} - }; - - explicit IntentsModel(WebIntentsRegistry* intents_registry); - virtual ~IntentsModel(); - - void AddIntentsTreeObserver(Observer* observer); - void RemoveIntentsTreeObserver(Observer* observer); - - string16 GetTreeNodeId(IntentsTreeNode* node); - IntentsTreeNode* GetTreeNode(std::string path_id); - void GetChildNodeList(IntentsTreeNode* parent, int start, int count, - base::ListValue* nodes); - void GetIntentsTreeNodeDictionary(const IntentsTreeNode& node, - base::DictionaryValue* dict); - - virtual void OnIntentsQueryDone( - WebIntentsRegistry::QueryID query_id, - const std::vector<WebIntentData>& intents) OVERRIDE; - - private: - // Loads the data model from the WebIntentsRegistry. - // TODO(gbillock): need an observer on that to absorb async updates? - void LoadModel(); - - // Do batch-specific notifies for updates coming from the LoadModel. - void NotifyObserverBeginBatch(); - void NotifyObserverEndBatch(); - - // The backing registry. Weak pointer. - WebIntentsRegistry* intents_registry_; - - // Separate list of observers that'll get batch updates. - ObserverList<Observer> intents_observer_list_; - - // Batch update nesting level. Incremented to indicate that we're in - // the middle of a batch update. - int batch_update_; -}; - -#endif // CHROME_BROWSER_UI_INTENTS_INTENTS_MODEL_H_ diff --git a/chrome/browser/ui/intents/intents_model_unittest.cc b/chrome/browser/ui/intents/intents_model_unittest.cc deleted file mode 100644 index 175e546..0000000 --- a/chrome/browser/ui/intents/intents_model_unittest.cc +++ /dev/null @@ -1,185 +0,0 @@ -// 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 "base/file_util.h" -#include "base/scoped_temp_dir.h" -#include "base/synchronization/waitable_event.h" -#include "base/values.h" -#include "base/utf_string_conversions.h" -#include "chrome/browser/intents/web_intents_registry.h" -#include "chrome/browser/webdata/web_data_service.h" -#include "chrome/test/base/testing_browser_process_test.h" -#include "chrome/browser/ui/intents/intents_model.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "ui/base/models/tree_node_model.h" - -class IntentsModelTest : public TestingBrowserProcessTest { - public: - IntentsModelTest() - : ui_thread_(BrowserThread::UI, &message_loop_), - db_thread_(BrowserThread::DB) {} - - protected: - virtual void SetUp() { - db_thread_.Start(); - wds_ = new WebDataService(); - ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); - wds_->Init(temp_dir_.path()); - - registry_.Initialize(wds_); - } - - virtual void TearDown() { - if (wds_.get()) - wds_->Shutdown(); - - db_thread_.Stop(); - MessageLoop::current()->PostTask(FROM_HERE, new MessageLoop::QuitTask); - MessageLoop::current()->Run(); - } - - void LoadRegistry() { - { - WebIntentData provider; - provider.service_url = GURL("http://www.google.com/share"); - provider.action = ASCIIToUTF16("SHARE"); - provider.type = ASCIIToUTF16("text/url"); - provider.title = ASCIIToUTF16("Google"); - registry_.RegisterIntentProvider(provider); - } - { - WebIntentData provider; - provider.service_url = GURL("http://picasaweb.google.com/share"); - provider.action = ASCIIToUTF16("EDIT"); - provider.type = ASCIIToUTF16("image/*"); - provider.title = ASCIIToUTF16("Picasa"); - registry_.RegisterIntentProvider(provider); - } - { - WebIntentData provider; - provider.service_url = GURL("http://www.digg.com/share"); - provider.action = ASCIIToUTF16("SHARE"); - provider.type = ASCIIToUTF16("text/url"); - provider.title = ASCIIToUTF16("Digg"); - registry_.RegisterIntentProvider(provider); - } - } - - MessageLoopForUI message_loop_; - BrowserThread ui_thread_; - BrowserThread db_thread_; - scoped_refptr<WebDataService> wds_; - WebIntentsRegistry registry_; - ScopedTempDir temp_dir_; -}; - -class WaitingIntentsObserver : public IntentsModel::Observer { - public: - WaitingIntentsObserver() : event_(true, false), added_(0) {} - - virtual void TreeModelBeginBatch(IntentsModel* model) {} - - virtual void TreeModelEndBatch(IntentsModel* model) { - event_.Signal(); - MessageLoop::current()->Quit(); - } - - virtual void TreeNodesAdded(ui::TreeModel* model, - ui::TreeModelNode* parent, - int start, - int count) { - added_++; - } - - virtual void TreeNodesRemoved(ui::TreeModel* model, - ui::TreeModelNode* node, - int start, - int count) { - } - - virtual void TreeNodeChanged(ui::TreeModel* model, ui::TreeModelNode* node) { - } - - void Wait() { - MessageLoop::current()->Run(); - event_.Wait(); - LOG(INFO) << "DONE!"; - } - - base::WaitableEvent event_; - int added_; -}; - -TEST_F(IntentsModelTest, NodeIDs) { - LoadRegistry(); - WaitingIntentsObserver obs; - IntentsModel intents_model(®istry_); - intents_model.AddIntentsTreeObserver(&obs); - obs.Wait(); - - IntentsTreeNode* n1 = new IntentsTreeNode(ASCIIToUTF16("origin")); - intents_model.Add(intents_model.GetRoot(), n1, - intents_model.GetRoot()->child_count()); - EXPECT_EQ(ASCIIToUTF16("origin"), intents_model.GetTreeNodeId(n1)); - - IntentsTreeNode* ncheck = intents_model.GetTreeNode("origin"); - EXPECT_EQ(ncheck, n1); - - base::ListValue nodes; - intents_model.GetChildNodeList( - intents_model.GetTreeNode("www.google.com"), 0, 1, &nodes); - EXPECT_EQ(static_cast<size_t>(1), nodes.GetSize()); - base::DictionaryValue* dict; - EXPECT_TRUE(nodes.GetDictionary(0, &dict)); - - std::string val; - EXPECT_TRUE(dict->GetString("site", &val)); - EXPECT_EQ("www.google.com", val); - EXPECT_TRUE(dict->GetString("name", &val)); - EXPECT_EQ("Google", val); - EXPECT_TRUE(dict->GetString("url", &val)); - EXPECT_EQ("http://www.google.com/share", val); - EXPECT_TRUE(dict->GetString("icon", &val)); - EXPECT_EQ("http://www.google.com/favicon.ico", val); - base::ListValue* types_list; - EXPECT_TRUE(dict->GetList("types", &types_list)); - EXPECT_EQ(static_cast<size_t>(1), types_list->GetSize()); - EXPECT_TRUE(types_list->GetString(0, &val)); - EXPECT_EQ("text/url", val); - bool bval; - EXPECT_TRUE(dict->GetBoolean("blocked", &bval)); - EXPECT_FALSE(bval); - EXPECT_TRUE(dict->GetBoolean("disabled", &bval)); - EXPECT_FALSE(bval); -} - -TEST_F(IntentsModelTest, LoadFromWebData) { - LoadRegistry(); - WaitingIntentsObserver obs; - IntentsModel intents_model(®istry_); - intents_model.AddIntentsTreeObserver(&obs); - obs.Wait(); - EXPECT_EQ(3, obs.added_); - - IntentsTreeNode* node = intents_model.GetTreeNode("www.google.com"); - ASSERT_NE(static_cast<IntentsTreeNode*>(NULL), node); - EXPECT_EQ(IntentsTreeNode::TYPE_ORIGIN, node->Type()); - EXPECT_EQ(ASCIIToUTF16("www.google.com"), node->GetTitle()); - EXPECT_EQ(1, node->child_count()); - node = node->GetChild(0); - ASSERT_EQ(IntentsTreeNode::TYPE_SERVICE, node->Type()); - ServiceTreeNode* snode = static_cast<ServiceTreeNode*>(node); - EXPECT_EQ(ASCIIToUTF16("Google"), snode->ServiceName()); - EXPECT_EQ(ASCIIToUTF16("SHARE"), snode->Action()); - EXPECT_EQ(ASCIIToUTF16("http://www.google.com/share"), snode->ServiceUrl()); - EXPECT_EQ(static_cast<size_t>(1), snode->Types().GetSize()); - string16 stype; - ASSERT_TRUE(snode->Types().GetString(0, &stype)); - EXPECT_EQ(ASCIIToUTF16("text/url"), stype); - - node = intents_model.GetTreeNode("www.digg.com"); - ASSERT_NE(static_cast<IntentsTreeNode*>(NULL), node); - EXPECT_EQ(IntentsTreeNode::TYPE_ORIGIN, node->Type()); - EXPECT_EQ(ASCIIToUTF16("www.digg.com"), node->GetTitle()); -} diff --git a/chrome/browser/ui/webui/options/intents_settings_handler.cc b/chrome/browser/ui/webui/options/intents_settings_handler.cc deleted file mode 100644 index 42f4868..0000000 --- a/chrome/browser/ui/webui/options/intents_settings_handler.cc +++ /dev/null @@ -1,159 +0,0 @@ -// 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/options/intents_settings_handler.h" - -#include "base/utf_string_conversions.h" -#include "base/values.h" -#include "chrome/browser/browsing_data_appcache_helper.h" -#include "chrome/browser/browsing_data_database_helper.h" -#include "chrome/browser/browsing_data_file_system_helper.h" -#include "chrome/browser/browsing_data_indexed_db_helper.h" -#include "chrome/browser/browsing_data_local_storage_helper.h" -#include "chrome/browser/intents/web_intents_registry.h" -#include "chrome/browser/intents/web_intents_registry_factory.h" -#include "chrome/browser/profiles/profile.h" -#include "chrome/browser/webdata/web_data_service.h" -#include "content/browser/webui/web_ui.h" -#include "grit/generated_resources.h" -#include "net/url_request/url_request_context_getter.h" -#include "ui/base/l10n/l10n_util.h" - -IntentsSettingsHandler::IntentsSettingsHandler() : batch_update_(false) { -} - -IntentsSettingsHandler::~IntentsSettingsHandler() { -} - -void IntentsSettingsHandler::GetLocalizedValues( - DictionaryValue* localized_strings) { - DCHECK(localized_strings); - - static OptionsStringResource resources[] = { - { "intentsDomain", IDS_INTENTS_DOMAIN_COLUMN_HEADER }, - { "intentsServiceData", IDS_INTENTS_SERVICE_DATA_COLUMN_HEADER }, - { "manageIntents", IDS_INTENTS_MANAGE_BUTTON }, - { "removeIntent", IDS_INTENTS_REMOVE_INTENT_BUTTON }, - }; - - RegisterStrings(localized_strings, resources, arraysize(resources)); - RegisterTitle(localized_strings, "intentsViewPage", - IDS_INTENTS_MANAGER_WINDOW_TITLE); -} - -void IntentsSettingsHandler::RegisterMessages() { - web_ui_->RegisterMessageCallback("removeIntent", - NewCallback(this, &IntentsSettingsHandler::RemoveIntent)); - web_ui_->RegisterMessageCallback("loadIntents", - NewCallback(this, &IntentsSettingsHandler::LoadChildren)); -} - -void IntentsSettingsHandler::TreeNodesAdded(ui::TreeModel* model, - ui::TreeModelNode* parent, - int start, - int count) { - SendChildren(intents_tree_model_->GetRoot()); -} - -void IntentsSettingsHandler::TreeNodesRemoved(ui::TreeModel* model, - ui::TreeModelNode* parent, - int start, - int count) { - SendChildren(intents_tree_model_->GetRoot()); -} - -void IntentsSettingsHandler::TreeModelBeginBatch(IntentsModel* model) { - batch_update_ = true; -} - -void IntentsSettingsHandler::TreeModelEndBatch(IntentsModel* model) { - batch_update_ = false; - - SendChildren(intents_tree_model_->GetRoot()); -} - -void IntentsSettingsHandler::EnsureIntentsModelCreated() { - if (intents_tree_model_.get()) return; - - Profile* profile = Profile::FromWebUI(web_ui_); - web_data_service_ = profile->GetWebDataService(Profile::EXPLICIT_ACCESS); - web_intents_registry_ = WebIntentsRegistryFactory::GetForProfile(profile); - web_intents_registry_->Initialize(web_data_service_.get()); - intents_tree_model_.reset(new IntentsModel(web_intents_registry_)); - intents_tree_model_->AddIntentsTreeObserver(this); -} - -void IntentsSettingsHandler::RemoveIntent(const base::ListValue* args) { - std::string node_path; - if (!args->GetString(0, &node_path)) { - return; - } - - EnsureIntentsModelCreated(); - - IntentsTreeNode* node = intents_tree_model_->GetTreeNode(node_path); - if (node->Type() == IntentsTreeNode::TYPE_ORIGIN) { - RemoveOrigin(node); - } else if (node->Type() == IntentsTreeNode::TYPE_SERVICE) { - ServiceTreeNode* snode = static_cast<ServiceTreeNode*>(node); - RemoveService(snode); - } -} - -void IntentsSettingsHandler::RemoveOrigin(IntentsTreeNode* node) { - // TODO(gbillock): This is a known batch update. Worth optimizing? - while (node->child_count() > 0) { - IntentsTreeNode* cnode = node->GetChild(0); - CHECK(cnode->Type() == IntentsTreeNode::TYPE_SERVICE); - ServiceTreeNode* snode = static_cast<ServiceTreeNode*>(cnode); - RemoveService(snode); - } - delete intents_tree_model_->Remove(node->parent(), node); -} - -void IntentsSettingsHandler::RemoveService(ServiceTreeNode* snode) { - WebIntentData provider; - provider.service_url = GURL(snode->ServiceUrl()); - provider.action = snode->Action(); - string16 stype; - if (snode->Types().GetString(0, &stype)) { - provider.type = stype; // Really need to iterate here. - } - provider.title = snode->ServiceName(); - LOG(INFO) << "Removing service " << snode->ServiceName() - << " " << snode->ServiceUrl(); - web_intents_registry_->UnregisterIntentProvider(provider); - delete intents_tree_model_->Remove(snode->parent(), snode); -} - -void IntentsSettingsHandler::LoadChildren(const base::ListValue* args) { - EnsureIntentsModelCreated(); - - std::string node_path; - if (!args->GetString(0, &node_path)) { - SendChildren(intents_tree_model_->GetRoot()); - return; - } - - IntentsTreeNode* node = intents_tree_model_->GetTreeNode(node_path); - SendChildren(node); -} - -void IntentsSettingsHandler::SendChildren(IntentsTreeNode* parent) { - // Early bailout during batch updates. We'll get one after the batch concludes - // with batch_update_ set false. - if (batch_update_) return; - - ListValue* children = new ListValue; - intents_tree_model_->GetChildNodeList(parent, 0, parent->child_count(), - children); - - ListValue args; - args.Append(parent == intents_tree_model_->GetRoot() ? - Value::CreateNullValue() : - Value::CreateStringValue(intents_tree_model_->GetTreeNodeId(parent))); - args.Append(children); - - web_ui_->CallJavascriptFunction("IntentsView.loadChildren", args); -} diff --git a/chrome/browser/ui/webui/options/intents_settings_handler.h b/chrome/browser/ui/webui/options/intents_settings_handler.h deleted file mode 100644 index 957284c..0000000 --- a/chrome/browser/ui/webui/options/intents_settings_handler.h +++ /dev/null @@ -1,78 +0,0 @@ -// 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_OPTIONS_INTENTS_SETTINGS_HANDLER_H_ -#define CHROME_BROWSER_UI_WEBUI_OPTIONS_INTENTS_SETTINGS_HANDLER_H_ -#pragma once - -#include "base/compiler_specific.h" -#include "base/memory/scoped_ptr.h" -#include "chrome/browser/ui/intents/intents_model.h" -#include "chrome/browser/ui/webui/options/options_ui.h" - -class WebDataService; -class WebIntentsRegistry; - -// Manage setting up the backing data for the web intents options page. -class IntentsSettingsHandler : public OptionsPageUIHandler, - public IntentsModel::Observer { - public: - IntentsSettingsHandler(); - virtual ~IntentsSettingsHandler(); - - // OptionsPageUIHandler implementation. - virtual void GetLocalizedValues(base::DictionaryValue* localized_strings); - virtual void RegisterMessages(); - - // IntentsModel::Observer implementation. - virtual void TreeNodesAdded(ui::TreeModel* model, - ui::TreeModelNode* parent, - int start, - int count) OVERRIDE; - virtual void TreeNodesRemoved(ui::TreeModel* model, - ui::TreeModelNode* parent, - int start, - int count) OVERRIDE; - virtual void TreeNodeChanged(ui::TreeModel* model, - ui::TreeModelNode* node) OVERRIDE {} - virtual void TreeModelBeginBatch(IntentsModel* model) OVERRIDE; - virtual void TreeModelEndBatch(IntentsModel* model) OVERRIDE; - - private: - // Creates the IntentsModel if neccessary. - void EnsureIntentsModelCreated(); - - // Updates search filter for cookies tree model. - void UpdateSearchResults(const base::ListValue* args); - - // Remove all sites data. - void RemoveAll(const base::ListValue* args); - - // Remove selected sites data. - void RemoveIntent(const base::ListValue* args); - - // Helper functions for removals. - void RemoveOrigin(IntentsTreeNode* node); - void RemoveService(ServiceTreeNode* snode); - - // Trigger for SendChildren to load the JS model. - void LoadChildren(const base::ListValue* args); - - // Get children nodes data and pass it to 'IntentsView.loadChildren' to - // update the WebUI. - void SendChildren(IntentsTreeNode* parent); - - scoped_refptr<WebDataService> web_data_service_; - WebIntentsRegistry* web_intents_registry_; // Weak pointer. - - // Backing data model for the intents list. - scoped_ptr<IntentsModel> intents_tree_model_; - - // Flag to indicate whether there is a batch update in progress. - bool batch_update_; - - DISALLOW_COPY_AND_ASSIGN(IntentsSettingsHandler); -}; - -#endif // CHROME_BROWSER_UI_WEBUI_OPTIONS_INTENTS_SETTINGS_HANDLER_H_ diff --git a/chrome/browser/ui/webui/options/options_ui.cc b/chrome/browser/ui/webui/options/options_ui.cc index 98e7d8b..0847472 100644 --- a/chrome/browser/ui/webui/options/options_ui.cc +++ b/chrome/browser/ui/webui/options/options_ui.cc @@ -28,7 +28,6 @@ #include "chrome/browser/ui/webui/options/core_options_handler.h" #include "chrome/browser/ui/webui/options/font_settings_handler.h" #include "chrome/browser/ui/webui/options/import_data_handler.h" -#include "chrome/browser/ui/webui/options/intents_settings_handler.h" #include "chrome/browser/ui/webui/options/language_options_handler.h" #include "chrome/browser/ui/webui/options/manage_profile_handler.h" #include "chrome/browser/ui/webui/options/options_sync_setup_handler.h" @@ -211,7 +210,6 @@ OptionsUI::OptionsUI(TabContents* contents) AddOptionsPageUIHandler(localized_strings, new ContentSettingsHandler()); AddOptionsPageUIHandler(localized_strings, new CookiesViewHandler()); AddOptionsPageUIHandler(localized_strings, new FontSettingsHandler()); - AddOptionsPageUIHandler(localized_strings, new IntentsSettingsHandler()); #if defined(OS_CHROMEOS) AddOptionsPageUIHandler(localized_strings, new chromeos::CrosLanguageOptionsHandler()); |