diff options
author | macourteau@chromium.org <macourteau@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-05-14 22:25:02 +0000 |
---|---|---|
committer | macourteau@chromium.org <macourteau@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-05-14 22:25:02 +0000 |
commit | e4196de4c47bdbf700f6d0e0fb0218cdb98e489e (patch) | |
tree | c7e1e9ca619525680bd2c5e46bf71d4f841ec163 | |
parent | da1cae582888c81287e2e6d898bf01e372cb323b (diff) | |
download | chromium_src-e4196de4c47bdbf700f6d0e0fb0218cdb98e489e.zip chromium_src-e4196de4c47bdbf700f6d0e0fb0218cdb98e489e.tar.gz chromium_src-e4196de4c47bdbf700f6d0e0fb0218cdb98e489e.tar.bz2 |
Adds basic information about suggestions to the chrome://suggestions-internals/ page.
BUG=none
TEST=Load the chrome://suggestions-internals/ page in Chrome, and make sure that there is a table shown with some data.
Review URL: https://chromiumcodereview.appspot.com/10389100
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@136993 0039d316-1c4b-4281-b951-d872f2087c98
10 files changed, 223 insertions, 29 deletions
diff --git a/chrome/browser/resources/suggestions_internals/suggestions_internals.css b/chrome/browser/resources/suggestions_internals/suggestions_internals.css index a5a1f91..08bd27b 100644 --- a/chrome/browser/resources/suggestions_internals/suggestions_internals.css +++ b/chrome/browser/resources/suggestions_internals/suggestions_internals.css @@ -2,4 +2,23 @@ * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ -/* TODO(macourteau): implement this, which is a placeholder. */ +.suggestions-debug-table { + border: 1px solid grey; + margin-bottom: 1.5em; +} + +.suggestions-debug-table th { + border: 1px solid grey; +} + +.suggestions-debug-table td { + border: 1px solid grey; +} + +p { + margin: 0; +} + +.input-section { + margin-bottom: 1em; +} diff --git a/chrome/browser/resources/suggestions_internals/suggestions_internals.html b/chrome/browser/resources/suggestions_internals/suggestions_internals.html index 6753722..c06690a 100644 --- a/chrome/browser/resources/suggestions_internals/suggestions_internals.html +++ b/chrome/browser/resources/suggestions_internals/suggestions_internals.html @@ -5,9 +5,21 @@ <title>Suggestions Internals</title> <link rel="stylesheet" href="suggestions_internals.css"> <script src="chrome://resources/js/cr.js"></script> + <script src="chrome://resources/js/util.js"></script> <script src="suggestions_internals.js"></script> </head> <body> - <!-- TODO(macourteau): implement this, which is a placeholder. --> + <div class="input-section"> + <form id="suggestions-form" action=""> + <p> + <input id="refresh-data" type="submit" value="Refresh data"> + </p> + <p> + <input id="show-discarded" type="checkbox"> + <label for="show-discarded">Show discarded items</label> + </p> + </form> + </div> + <div id="suggestions-debug-text"></div> </body> </html> diff --git a/chrome/browser/resources/suggestions_internals/suggestions_internals.js b/chrome/browser/resources/suggestions_internals/suggestions_internals.js index 7e51da0..4929ef8 100644 --- a/chrome/browser/resources/suggestions_internals/suggestions_internals.js +++ b/chrome/browser/resources/suggestions_internals/suggestions_internals.js @@ -17,11 +17,128 @@ cr.define('suggestionsInternals', function() { * Register our event handlers. */ function initialize() { - // TODO(macourteau): implement this. + $('suggestions-form').addEventListener('submit', onRefreshClicked); + $('show-discarded').addEventListener('change', refresh); + refresh(); + } + + /** + * Called when the 'Refresh' button is clicked. Reloads the suggestions data. + */ + function onRefreshClicked(event) { + refresh(); + event.preventDefault(); + } + + /** + * Reloads the suggestions data by sending a 'getSuggestions' message to + * Chrome. The C++ code is then expected to call 'setSuggestions' when there + * are suggestions ready. + */ + function refresh() { + chrome.send('getSuggestions'); + } + + /** + * A list of columns that we do not want to display. + * @type {Array.<string>} + * @const + */ + var IGNORED_COLUMNS = [ + 'direction' + ]; + + /** + * A list specifying the name of the first columns to be displayed. If + * present, they will be displayed in this order, followed by the remaining + * columns. + * @type {Array.<string>} + * @const + */ + var PREFERRED_COLUMN_ORDER = [ + 'title', + 'url', + 'score' + ]; + + /** + * Called by Chrome code, with a ranked list of suggestions. The columns + * to be displayed are calculated automatically from the properties of the + * elements in the list, such that all properties have a column. + */ + function setSuggestions(list) { + // Build a list of all the columns that will be displayed. + var columns = []; + list.forEach(function(entry) { + for (var column in entry) { + if (columns.indexOf(column) < 0) + columns.push(column); + } + }); + + // Remove columns that we don't want to display. + columns = columns.filter(function(column) { + return IGNORED_COLUMNS.indexOf(column) < 0; + }); + + // Move the preferred columns to the start of the column list. + for (var i = PREFERRED_COLUMN_ORDER.length - 1; i >= 0; i--) { + var index = columns.indexOf(PREFERRED_COLUMN_ORDER[i]); + if (index >= 0) + columns.unshift(columns.splice(index, 1)[0]); + } + + // Prepend a "Rank" column. + columns.unshift('rank'); + + // Erase whatever is currently being displayed. + var output = $('suggestions-debug-text'); + output.innerHTML = ''; + + // Create the container table and add the header row. + var table = document.createElement('table'); + table.className = 'suggestions-debug-table'; + var header = document.createElement('tr'); + columns.forEach(function(entry) { + var column = document.createElement('th'); + column.innerText = entry; + header.appendChild(column); + }); + table.appendChild(header); + + // Add all the suggestions to the table. + var rank = 1; + list.forEach(function(entry) { + var row = document.createElement('tr'); + columns.forEach(function(column_name) { + var column = document.createElement('td'); + // Only add the column if the current suggestion has this property + // (otherwise, leave the cell empty). + if (entry.hasOwnProperty(column_name)) { + var data = entry[column_name]; + // If the text is a URL, make it an anchor element. + if (/^https?:\/\/.+$/.test(data)) { + var anchor = document.createElement('a'); + anchor.href = data; + anchor.innerText = data; + column.appendChild(anchor); + } else { + column.innerText = data; + } + } else if (column_name == 'rank') { + column.innerText = rank++; + } + row.appendChild(column); + }); + table.appendChild(row); + }); + + output.appendChild(table); } return { initialize: initialize, + setSuggestions: setSuggestions }; }); diff --git a/chrome/browser/ui/webui/ntp/suggestions_combiner.cc b/chrome/browser/ui/webui/ntp/suggestions_combiner.cc index 7a6b623..2500d2f 100644 --- a/chrome/browser/ui/webui/ntp/suggestions_combiner.cc +++ b/chrome/browser/ui/webui/ntp/suggestions_combiner.cc @@ -22,14 +22,14 @@ SuggestionsCombiner::SuggestionsCombiner( : sources_fetching_count_(0), delegate_(delegate), suggestions_count_(kSuggestionsCount), - pages_value_(new base::ListValue()) { + page_values_(new base::ListValue()) { } SuggestionsCombiner::~SuggestionsCombiner() { } -base::ListValue* SuggestionsCombiner::GetPagesValue() { - return pages_value_.get(); +base::ListValue* SuggestionsCombiner::GetPageValues() { + return page_values_.get(); } void SuggestionsCombiner::FetchItems(Profile* profile) { @@ -44,13 +44,13 @@ void SuggestionsCombiner::AddSource(SuggestionsSource* source) { sources_.push_back(source); } -void SuggestionsCombiner::FillPagesValue() { +void SuggestionsCombiner::FillPageValues() { int total_weight = 0; for (size_t i = 0; i < sources_.size(); ++i) total_weight += sources_[i]->GetWeight(); DCHECK_GT(total_weight, 0); - pages_value_.reset(new base::ListValue()); + page_values_.reset(new base::ListValue()); // Evaluate how many items to obtain from each sources. We use error diffusion // to ensure that we get the total desired number of items. @@ -66,8 +66,8 @@ void SuggestionsCombiner::FillPagesValue() { sources_[i]->GetItemCount()); for (int j = 0; j < item_count; ++j) - pages_value_->Append(sources_[i]->PopItem()); - next_item_index_for_source.push_back(pages_value_->GetSize()); + page_values_->Append(sources_[i]->PopItem()); + next_item_index_for_source.push_back(page_values_->GetSize()); } // Fill in extra items, prioritizing the first source. @@ -76,12 +76,12 @@ void SuggestionsCombiner::FillPagesValue() { // number of extra items that were added and offset indices by that much. size_t extra_items_added = 0; for (size_t i = 0; i < sources_.size() && - pages_value_->GetSize() < suggestions_count_; ++i) { + page_values_->GetSize() < suggestions_count_; ++i) { size_t index = next_item_index_for_source[i] + extra_items_added; - while (pages_value_->GetSize() < suggestions_count_ && + while (page_values_->GetSize() < suggestions_count_ && (item = sources_[i]->PopItem())) { - pages_value_->Insert(index++, item); + page_values_->Insert(index++, item); extra_items_added++; } } @@ -91,7 +91,11 @@ void SuggestionsCombiner::OnItemsReady() { DCHECK_GT(sources_fetching_count_, 0); sources_fetching_count_--; if (sources_fetching_count_ == 0) { - FillPagesValue(); + FillPageValues(); delegate_->OnSuggestionsReady(); } } + +void SuggestionsCombiner::SetSuggestionsCount(size_t suggestions_count) { + suggestions_count_ = suggestions_count; +} diff --git a/chrome/browser/ui/webui/ntp/suggestions_combiner.h b/chrome/browser/ui/webui/ntp/suggestions_combiner.h index 65253f3..5548efa 100644 --- a/chrome/browser/ui/webui/ntp/suggestions_combiner.h +++ b/chrome/browser/ui/webui/ntp/suggestions_combiner.h @@ -43,18 +43,20 @@ class SuggestionsCombiner { // Fetch a new set of items from the various suggestion sources. void FetchItems(Profile* profile); - base::ListValue* GetPagesValue(); + base::ListValue* GetPageValues(); // Called by a source when its items are ready. Make sure suggestion sources // call this method exactly once for each call to // SuggestionsSource::FetchItems. void OnItemsReady(); + void SetSuggestionsCount(size_t suggestions_count); + private: - // Fill the pages value from the suggestion sources so they can be sent to - // the javascript side. This should only be called when all the suggestion + // Fill the page values from the suggestion sources so they can be sent to + // the JavaScript side. This should only be called when all the suggestion // sources have items ready. - void FillPagesValue(); + void FillPageValues(); typedef ScopedVector<SuggestionsSource> SuggestionsSources; @@ -74,7 +76,7 @@ class SuggestionsCombiner { size_t suggestions_count_; // Informations to send to the javascript side. - scoped_ptr<base::ListValue> pages_value_; + scoped_ptr<base::ListValue> page_values_; DISALLOW_COPY_AND_ASSIGN(SuggestionsCombiner); }; diff --git a/chrome/browser/ui/webui/ntp/suggestions_combiner_unittest.cc b/chrome/browser/ui/webui/ntp/suggestions_combiner_unittest.cc index 817419c..01cea13 100644 --- a/chrome/browser/ui/webui/ntp/suggestions_combiner_unittest.cc +++ b/chrome/browser/ui/webui/ntp/suggestions_combiner_unittest.cc @@ -274,14 +274,14 @@ class SuggestionsCombinerTest : public testing::Test { TEST_F(SuggestionsCombinerTest, NoSource) { combiner_->FetchItems(NULL); - EXPECT_EQ(0UL, combiner_->GetPagesValue()->GetSize()); + EXPECT_EQ(0UL, combiner_->GetPageValues()->GetSize()); } TEST_F(SuggestionsCombinerTest, SourcesAreNotDoneFetching) { combiner_->AddSource(new SuggestionsSourceStub(1, "sourceA", 10)); combiner_->AddSource(new SuggestionsSourceStub(1, "sourceB", 10)); combiner_->FetchItems(NULL); - EXPECT_EQ(0UL, combiner_->GetPagesValue()->GetSize()); + EXPECT_EQ(0UL, combiner_->GetPageValues()->GetSize()); } TEST_F(SuggestionsCombinerTest, TestSuite) { @@ -317,7 +317,7 @@ TEST_F(SuggestionsCombinerTest, TestSuite) { } // Verify expectations. - base::ListValue* results = combiner_->GetPagesValue(); + base::ListValue* results = combiner_->GetPageValues(); size_t result_count = results->GetSize(); EXPECT_LE(result_count, 8UL); for (size_t j = 0; j < 8; ++j) { diff --git a/chrome/browser/ui/webui/ntp/suggestions_page_handler.cc b/chrome/browser/ui/webui/ntp/suggestions_page_handler.cc index a7b6a133..b6c2ffc 100644 --- a/chrome/browser/ui/webui/ntp/suggestions_page_handler.cc +++ b/chrome/browser/ui/webui/ntp/suggestions_page_handler.cc @@ -131,12 +131,12 @@ void SuggestionsHandler::OnSuggestionsReady() { } void SuggestionsHandler::SendPagesValue() { - if (suggestions_combiner_->GetPagesValue()) { + if (suggestions_combiner_->GetPageValues()) { // TODO(georgey) add actual blacklist. bool has_blacklisted_urls = false; base::FundamentalValue has_blacklisted_urls_value(has_blacklisted_urls); web_ui()->CallJavascriptFunction("ntp.setSuggestionsPages", - *suggestions_combiner_->GetPagesValue(), + *suggestions_combiner_->GetPageValues(), has_blacklisted_urls_value); } } diff --git a/chrome/browser/ui/webui/ntp/suggestions_page_handler.h b/chrome/browser/ui/webui/ntp/suggestions_page_handler.h index f195570..bf0a3e5 100644 --- a/chrome/browser/ui/webui/ntp/suggestions_page_handler.h +++ b/chrome/browser/ui/webui/ntp/suggestions_page_handler.h @@ -63,7 +63,7 @@ class SuggestionsHandler : public content::WebUIMessageHandler, const content::NotificationSource& source, const content::NotificationDetails& details) OVERRIDE; - // SuggestionsCombiner::Delegate implementation + // SuggestionsCombiner::Delegate implementation. virtual void OnSuggestionsReady() OVERRIDE; static void RegisterUserPrefs(PrefService* prefs); diff --git a/chrome/browser/ui/webui/suggestions_internals/suggestions_internals_ui_handler.cc b/chrome/browser/ui/webui/suggestions_internals/suggestions_internals_ui_handler.cc index 80bbfd2..48d621ba 100644 --- a/chrome/browser/ui/webui/suggestions_internals/suggestions_internals_ui_handler.cc +++ b/chrome/browser/ui/webui/suggestions_internals/suggestions_internals_ui_handler.cc @@ -5,15 +5,45 @@ #include "chrome/browser/ui/webui/suggestions_internals/suggestions_internals_ui_handler.h" #include "base/bind.h" +#include "base/values.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/ui/webui/chrome_url_data_manager.h" +#include "chrome/browser/ui/webui/ntp/suggestions_combiner.h" +#include "chrome/browser/ui/webui/ntp/suggestions_source_discovery.h" +#include "chrome/browser/ui/webui/ntp/suggestions_source_top_sites.h" #include "content/public/browser/web_ui.h" -// TODO(macourteau): implement this class. It's currently a placeholder for -// handling the WebUI for chrome://suggestions-internals/. +namespace { + +const size_t kSuggestionsCount = 100; + +} // namespace + SuggestionsInternalsUIHandler::SuggestionsInternalsUIHandler(Profile* profile) { } SuggestionsInternalsUIHandler::~SuggestionsInternalsUIHandler() {} +void SuggestionsInternalsUIHandler::OnSuggestionsReady() { + if (suggestions_combiner_->GetPageValues()) { + web_ui()->CallJavascriptFunction("suggestionsInternals.setSuggestions", + *suggestions_combiner_->GetPageValues()); + } +} + void SuggestionsInternalsUIHandler::RegisterMessages() { - // TODO(macourteau): implement this. + // Setup the suggestions sources. + suggestions_combiner_.reset(new SuggestionsCombiner(this)); + suggestions_combiner_->AddSource(new SuggestionsSourceTopSites()); + suggestions_combiner_->AddSource(new SuggestionsSourceDiscovery()); + suggestions_combiner_->SetSuggestionsCount(kSuggestionsCount); + + web_ui()->RegisterMessageCallback("getSuggestions", + base::Bind(&SuggestionsInternalsUIHandler::HandleGetSuggestions, + base::Unretained(this))); +} + +void SuggestionsInternalsUIHandler::HandleGetSuggestions( + const base::ListValue* one_element_input_string) { + suggestions_combiner_->FetchItems(Profile::FromWebUI(web_ui())); } diff --git a/chrome/browser/ui/webui/suggestions_internals/suggestions_internals_ui_handler.h b/chrome/browser/ui/webui/suggestions_internals/suggestions_internals_ui_handler.h index d55f46e..4dab866 100644 --- a/chrome/browser/ui/webui/suggestions_internals/suggestions_internals_ui_handler.h +++ b/chrome/browser/ui/webui/suggestions_internals/suggestions_internals_ui_handler.h @@ -8,21 +8,31 @@ #include "base/memory/scoped_ptr.h" #include "base/time.h" +#include "chrome/browser/ui/webui/ntp/suggestions_combiner.h" #include "content/public/browser/web_ui_message_handler.h" class Profile; // UI Handler for chrome://suggestions-internals/ -class SuggestionsInternalsUIHandler : public content::WebUIMessageHandler { +class SuggestionsInternalsUIHandler : public content::WebUIMessageHandler, + public SuggestionsCombiner::Delegate { public: explicit SuggestionsInternalsUIHandler(Profile* profile); virtual ~SuggestionsInternalsUIHandler(); + // SuggestionsCombiner::Delegate implementation. + virtual void OnSuggestionsReady() OVERRIDE; + protected: // WebUIMessageHandler implementation. // Register our handler to get callbacks from javascript. virtual void RegisterMessages() OVERRIDE; + void HandleGetSuggestions(const base::ListValue* one_element_input_string); + + // Used to combine suggestions from various sources. + scoped_ptr<SuggestionsCombiner> suggestions_combiner_; + DISALLOW_COPY_AND_ASSIGN(SuggestionsInternalsUIHandler); }; |