summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormacourteau@chromium.org <macourteau@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-05-14 22:25:02 +0000
committermacourteau@chromium.org <macourteau@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-05-14 22:25:02 +0000
commite4196de4c47bdbf700f6d0e0fb0218cdb98e489e (patch)
treec7e1e9ca619525680bd2c5e46bf71d4f841ec163
parentda1cae582888c81287e2e6d898bf01e372cb323b (diff)
downloadchromium_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
-rw-r--r--chrome/browser/resources/suggestions_internals/suggestions_internals.css21
-rw-r--r--chrome/browser/resources/suggestions_internals/suggestions_internals.html14
-rw-r--r--chrome/browser/resources/suggestions_internals/suggestions_internals.js119
-rw-r--r--chrome/browser/ui/webui/ntp/suggestions_combiner.cc26
-rw-r--r--chrome/browser/ui/webui/ntp/suggestions_combiner.h12
-rw-r--r--chrome/browser/ui/webui/ntp/suggestions_combiner_unittest.cc6
-rw-r--r--chrome/browser/ui/webui/ntp/suggestions_page_handler.cc4
-rw-r--r--chrome/browser/ui/webui/ntp/suggestions_page_handler.h2
-rw-r--r--chrome/browser/ui/webui/suggestions_internals/suggestions_internals_ui_handler.cc36
-rw-r--r--chrome/browser/ui/webui/suggestions_internals/suggestions_internals_ui_handler.h12
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);
};