summaryrefslogtreecommitdiffstats
path: root/chrome
diff options
context:
space:
mode:
Diffstat (limited to 'chrome')
-rw-r--r--chrome/app/generated_resources.grd16
-rw-r--r--chrome/app/theme/ntp_x_icon.pngbin0 -> 2680 bytes
-rw-r--r--chrome/app/theme/ntp_x_icon_active.pngbin0 -> 2565 bytes
-rw-r--r--chrome/app/theme/ntp_x_icon_hover.pngbin0 -> 2531 bytes
-rw-r--r--chrome/app/theme/ntp_x_icon_small.pngbin0 -> 785 bytes
-rw-r--r--chrome/browser/browser_prefs.cc2
-rw-r--r--chrome/browser/dom_ui/new_tab_ui.cc105
-rw-r--r--chrome/browser/dom_ui/new_tab_ui.h3
-rw-r--r--chrome/browser/history/history.cc3
-rw-r--r--chrome/browser/history/history.h1
-rw-r--r--chrome/browser/history/history_backend.cc5
-rw-r--r--chrome/browser/history/history_backend.h3
-rw-r--r--chrome/browser/history/history_unittest.cc6
-rw-r--r--chrome/browser/history/visitsegment_database.cc8
-rw-r--r--chrome/browser/history/visitsegment_database.h4
-rw-r--r--chrome/browser/resources/new_tab.html128
-rw-r--r--chrome/common/pref_names.cc3
-rw-r--r--chrome/common/pref_names.h2
18 files changed, 258 insertions, 31 deletions
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd
index 33cbe02..4c2cc64 100644
--- a/chrome/app/generated_resources.grd
+++ b/chrome/app/generated_resources.grd
@@ -3033,6 +3033,22 @@ each locale. -->
desc="The 'Show history' link on the new tab page">
Show full history
</message>
+ <message name="IDS_NEW_TAB_EDIT_THUMBNAILS"
+ desc="The 'Edit thumbnails' link on the new tab page">
+ Edit thumbnails
+ </message>
+ <message name="IDS_NEW_TAB_MOST_VISITED_DONE_EDITING_BUTTON"
+ desc="The caption of the button used to exit the edit thumbnails mode">
+ Done editing
+ </message>
+ <message name="IDS_NEW_TAB_RESTORE_THUMBNAILS_LINK"
+ desc="The link that restores previously removed thumbnails">
+ Restore all removed thumbnails
+ </message>
+ <message name="IDS_NEW_TAB_MOST_VISITED_EDIT_MODE_HEADING"
+ desc="The new tab page heading when in edit thumbnails mode.">
+ Click <ph name="CROSS_IMAGE">&lt;div id="cross-image-container"&gt;&lt;/div&gt;</ph> to remove the thumbnail
+ </message>
<message name="IDS_NEW_TAB_HISTORY_SEARCH"
desc="The label for the field that searches the user's history on the new tab page">
Search your history
diff --git a/chrome/app/theme/ntp_x_icon.png b/chrome/app/theme/ntp_x_icon.png
new file mode 100644
index 0000000..1fcc1a4
--- /dev/null
+++ b/chrome/app/theme/ntp_x_icon.png
Binary files differ
diff --git a/chrome/app/theme/ntp_x_icon_active.png b/chrome/app/theme/ntp_x_icon_active.png
new file mode 100644
index 0000000..ac50454
--- /dev/null
+++ b/chrome/app/theme/ntp_x_icon_active.png
Binary files differ
diff --git a/chrome/app/theme/ntp_x_icon_hover.png b/chrome/app/theme/ntp_x_icon_hover.png
new file mode 100644
index 0000000..466ada1
--- /dev/null
+++ b/chrome/app/theme/ntp_x_icon_hover.png
Binary files differ
diff --git a/chrome/app/theme/ntp_x_icon_small.png b/chrome/app/theme/ntp_x_icon_small.png
new file mode 100644
index 0000000..16792d1
--- /dev/null
+++ b/chrome/app/theme/ntp_x_icon_small.png
Binary files differ
diff --git a/chrome/browser/browser_prefs.cc b/chrome/browser/browser_prefs.cc
index 7e9d6d8..b7b1836 100644
--- a/chrome/browser/browser_prefs.cc
+++ b/chrome/browser/browser_prefs.cc
@@ -8,6 +8,7 @@
#include "chrome/browser/bookmarks/bookmark_utils.h"
#include "chrome/browser/browser.h"
#include "chrome/browser/browser_shutdown.h"
+#include "chrome/browser/dom_ui/new_tab_ui.h"
#include "chrome/browser/download/download_manager.h"
#include "chrome/browser/external_protocol_handler.h"
#include "chrome/browser/google_url_tracker.h"
@@ -62,6 +63,7 @@ void RegisterAllPrefs(PrefService* user_prefs, PrefService* local_state) {
TabContents::RegisterUserPrefs(user_prefs);
TemplateURLPrepopulateData::RegisterUserPrefs(user_prefs);
WebContents::RegisterUserPrefs(user_prefs);
+ NewTabUI::RegisterUserPrefs(user_prefs);
}
} // namespace browser
diff --git a/chrome/browser/dom_ui/new_tab_ui.cc b/chrome/browser/dom_ui/new_tab_ui.cc
index 15bbaa6..c4da817 100644
--- a/chrome/browser/dom_ui/new_tab_ui.cc
+++ b/chrome/browser/dom_ui/new_tab_ui.cc
@@ -44,7 +44,7 @@
namespace {
// The number of most visited pages we show.
-const int kMostVisitedPages = 9;
+const size_t kMostVisitedPages = 9;
// The number of days of history we consider for most visited entries.
const int kMostVisitedScope = 90;
@@ -245,6 +245,14 @@ void NewTabHTMLSource::StartDataRequest(const std::string& path,
l10n_util::GetString(IDS_NEW_TAB_HISTORY_SHOW));
localized_strings.SetString(L"showhistoryurl",
chrome::kChromeUIHistoryURL);
+ localized_strings.SetString(L"editthumbnails",
+ l10n_util::GetString(IDS_NEW_TAB_EDIT_THUMBNAILS));
+ localized_strings.SetString(L"restorethumbnails",
+ l10n_util::GetString(IDS_NEW_TAB_RESTORE_THUMBNAILS_LINK));
+ localized_strings.SetString(L"editmodeheading",
+ l10n_util::GetString(IDS_NEW_TAB_MOST_VISITED_EDIT_MODE_HEADING));
+ localized_strings.SetString(L"doneediting",
+ l10n_util::GetString(IDS_NEW_TAB_MOST_VISITED_DONE_EDITING_BUTTON));
localized_strings.SetString(L"searchhistory",
l10n_util::GetString(IDS_NEW_TAB_HISTORY_SEARCH));
localized_strings.SetString(L"recentlyclosed",
@@ -343,6 +351,12 @@ class MostVisitedHandler : public DOMMessageHandler,
// Callback for the "getMostVisited" message.
void HandleGetMostVisited(const Value* value);
+ // Callback for the "blacklistURLFromMostVisited" message.
+ void HandleBlacklistURL(const Value* url);
+
+ // Callback for the "clearMostVisitedURLsBlacklist" message.
+ void HandleClearBlacklist(const Value* url);
+
// NotificationObserver implementation.
virtual void Observe(NotificationType type,
const NotificationSource& source,
@@ -352,12 +366,21 @@ class MostVisitedHandler : public DOMMessageHandler,
return most_visited_urls_;
}
+ static void RegisterUserPrefs(PrefService* prefs);
+
private:
// Callback from the history system when the most visited list is available.
void OnSegmentUsageAvailable(CancelableRequestProvider::Handle handle,
std::vector<PageUsageData*>* data);
- DOMUI* dom_ui_;
+ // Puts the passed URL in the blacklist (so it does not show as a thumbnail).
+ void BlacklistURL(const GURL& url);
+
+ // Returns true if the passed URL has been blacklisted.
+ bool IsURLBlacklisted(const GURL& url);
+
+ // Returns the URL blacklist.
+ ListValue* GetURLBlacklist();
// Our consumer for the history service.
CancelableRequestConsumerTSimple<PageUsageData*> cancelable_consumer_;
@@ -371,13 +394,18 @@ class MostVisitedHandler : public DOMMessageHandler,
};
MostVisitedHandler::MostVisitedHandler(DOMUI* dom_ui)
- : DOMMessageHandler(dom_ui),
- dom_ui_(dom_ui) {
+ : DOMMessageHandler(dom_ui) {
// Register ourselves as the handler for the "mostvisited" message from
// Javascript.
dom_ui_->RegisterMessageCallback("getMostVisited",
NewCallback(this, &MostVisitedHandler::HandleGetMostVisited));
+ // Also register ourselves for any most-visited item blacklisting.
+ dom_ui_->RegisterMessageCallback("blacklistURLFromMostVisited",
+ NewCallback(this, &MostVisitedHandler::HandleBlacklistURL));
+ dom_ui_->RegisterMessageCallback("clearMostVisitedURLsBlacklist",
+ NewCallback(this, &MostVisitedHandler::HandleClearBlacklist));
+
// Set up our sources for thumbnail and favicon data. Since we may be in
// testing mode with no I/O thread, only add our handler when an I/O thread
// exists. Ownership is passed to the ChromeURLDataManager.
@@ -405,27 +433,58 @@ MostVisitedHandler::~MostVisitedHandler() {
}
void MostVisitedHandler::HandleGetMostVisited(const Value* value) {
+ const int kMostVisitedCount = 9;
+ // Let's query for the number of items we want plus the blacklist size as
+ // we'll be filtering-out the returned list with the blacklist URLs.
+ int result_count = kMostVisitedCount + GetURLBlacklist()->GetSize();
HistoryService* hs =
dom_ui_->GetProfile()->GetHistoryService(Profile::EXPLICIT_ACCESS);
hs->QuerySegmentUsageSince(
&cancelable_consumer_,
base::Time::Now() - base::TimeDelta::FromDays(kMostVisitedScope),
+ result_count,
NewCallback(this, &MostVisitedHandler::OnSegmentUsageAvailable));
}
+void MostVisitedHandler::HandleBlacklistURL(const Value* value) {
+ if (!value->IsType(Value::TYPE_LIST)) {
+ NOTREACHED();
+ return;
+ }
+ std::string url;
+ const ListValue* list = static_cast<const ListValue*>(value);
+ if (list->GetSize() == 0 || !list->GetString(0, &url)) {
+ NOTREACHED();
+ return;
+ }
+ BlacklistURL(GURL(url));
+ // Force a refresh of the thumbnails.
+ HandleGetMostVisited(NULL);
+}
+
+void MostVisitedHandler::HandleClearBlacklist(const Value* value) {
+ GetURLBlacklist()->Clear();
+ // Force a refresh of the thumbnails.
+ HandleGetMostVisited(NULL);
+}
+
void MostVisitedHandler::OnSegmentUsageAvailable(
CancelableRequestProvider::Handle handle,
std::vector<PageUsageData*>* data) {
most_visited_urls_.clear();
ListValue pages_value;
- const size_t count = std::min<size_t>(kMostVisitedPages, data->size());
- for (size_t i = 0; i < count; ++i) {
+ for (size_t i = 0; i < data->size(); ++i) {
const PageUsageData& page = *(*data)[i];
+ GURL url = page.GetURL();
+ if (IsURLBlacklisted(url))
+ continue;
DictionaryValue* page_value = new DictionaryValue;
SetURLTitleAndDirection(page_value, page.GetTitle(), page.GetURL());
pages_value.Append(page_value);
most_visited_urls_.push_back(page.GetURL());
+ if (most_visited_urls_.size() >= kMostVisitedPages)
+ break;
}
dom_ui_->CallJavascriptFunction(L"mostVisitedPages", pages_value);
}
@@ -442,6 +501,36 @@ void MostVisitedHandler::Observe(NotificationType type,
HandleGetMostVisited(NULL);
}
+void MostVisitedHandler::BlacklistURL(const GURL& url) {
+ if (IsURLBlacklisted(url))
+ return;
+ GetURLBlacklist()->Append(Value::CreateStringValue(url.spec()));
+}
+
+bool MostVisitedHandler::IsURLBlacklisted(const GURL& url) {
+ std::string url_spec = url.spec();
+ ListValue* blacklist = GetURLBlacklist();
+ for (ListValue::const_iterator iter = blacklist->begin();
+ iter != blacklist->end(); ++iter) {
+ std::string blacklisted_url;
+ bool success = (*iter)->GetAsString(&blacklisted_url);
+ DCHECK(success);
+ if (url_spec == blacklisted_url)
+ return true;
+ }
+ return false;
+}
+
+ListValue* MostVisitedHandler::GetURLBlacklist() {
+ return dom_ui_->GetProfile()->GetPrefs()->
+ GetMutableList(prefs::kNTPMostVisitedURLsBlacklist);
+}
+
+// static
+void MostVisitedHandler::RegisterUserPrefs(PrefService* prefs) {
+ prefs->RegisterListPref(prefs::kNTPMostVisitedURLsBlacklist);
+}
+
///////////////////////////////////////////////////////////////////////////////
// TemplateURLHandler
@@ -1063,3 +1152,7 @@ NewTabUI::NewTabUI(WebContents* contents)
NewTabUI::~NewTabUI() {
}
+// static
+void NewTabUI::RegisterUserPrefs(PrefService* prefs) {
+ MostVisitedHandler::RegisterUserPrefs(prefs);
+}
diff --git a/chrome/browser/dom_ui/new_tab_ui.h b/chrome/browser/dom_ui/new_tab_ui.h
index 8dedbd5..ef101b3 100644
--- a/chrome/browser/dom_ui/new_tab_ui.h
+++ b/chrome/browser/dom_ui/new_tab_ui.h
@@ -8,6 +8,7 @@
#include "chrome/browser/dom_ui/dom_ui.h"
class GURL;
+class PrefService;
class Profile;
// The TabContents used for the New Tab page.
@@ -16,6 +17,8 @@ class NewTabUI : public DOMUI {
explicit NewTabUI(WebContents* manager);
~NewTabUI();
+ static void RegisterUserPrefs(PrefService* prefs);
+
private:
// The message id that should be displayed in this NewTabUIContents
// instance's motd area.
diff --git a/chrome/browser/history/history.cc b/chrome/browser/history/history.cc
index 33eb4d9..7e1130c 100644
--- a/chrome/browser/history/history.cc
+++ b/chrome/browser/history/history.cc
@@ -242,10 +242,11 @@ HistoryService::Handle HistoryService::ScheduleDBTask(
HistoryService::Handle HistoryService::QuerySegmentUsageSince(
CancelableRequestConsumerBase* consumer,
const Time from_time,
+ int max_result_count,
SegmentQueryCallback* callback) {
return Schedule(PRIORITY_UI, &HistoryBackend::QuerySegmentUsage,
consumer, new history::QuerySegmentUsageRequest(callback),
- from_time);
+ from_time, max_result_count);
}
void HistoryService::SetOnBackendDestroyTask(Task* task) {
diff --git a/chrome/browser/history/history.h b/chrome/browser/history/history.h
index d47f12f..eb62217 100644
--- a/chrome/browser/history/history.h
+++ b/chrome/browser/history/history.h
@@ -468,6 +468,7 @@ class HistoryService : public CancelableRequestProvider,
// representing the segment.
Handle QuerySegmentUsageSince(CancelableRequestConsumerBase* consumer,
const base::Time from_time,
+ int max_result_count,
SegmentQueryCallback* callback);
// Set the presentation index for the segment identified by |segment_id|.
diff --git a/chrome/browser/history/history_backend.cc b/chrome/browser/history/history_backend.cc
index 48a8373..d045dc9 100644
--- a/chrome/browser/history/history_backend.cc
+++ b/chrome/browser/history/history_backend.cc
@@ -846,12 +846,13 @@ void HistoryBackend::SetSegmentPresentationIndex(SegmentID segment_id,
void HistoryBackend::QuerySegmentUsage(
scoped_refptr<QuerySegmentUsageRequest> request,
- const Time from_time) {
+ const Time from_time,
+ int max_result_count) {
if (request->canceled())
return;
if (db_.get()) {
- db_->QuerySegmentUsage(from_time, &request->value.get());
+ db_->QuerySegmentUsage(from_time, max_result_count, &request->value.get());
// If this is the first time we query segments, invoke
// DeleteOldSegmentData asynchronously. We do this to cleanup old
diff --git a/chrome/browser/history/history_backend.h b/chrome/browser/history/history_backend.h
index 7a66008..6201ec6 100644
--- a/chrome/browser/history/history_backend.h
+++ b/chrome/browser/history/history_backend.h
@@ -208,7 +208,8 @@ class HistoryBackend : public base::RefCountedThreadSafe<HistoryBackend>,
// Segment usage -------------------------------------------------------------
void QuerySegmentUsage(scoped_refptr<QuerySegmentUsageRequest> request,
- const base::Time from_time);
+ const base::Time from_time,
+ int max_result_count);
void DeleteOldSegmentData();
void SetSegmentPresentationIndex(SegmentID segment_id, int index);
diff --git a/chrome/browser/history/history_unittest.cc b/chrome/browser/history/history_unittest.cc
index 107d845..e64a09d 100644
--- a/chrome/browser/history/history_unittest.cc
+++ b/chrome/browser/history/history_unittest.cc
@@ -598,7 +598,7 @@ TEST_F(HistoryTest, Segments) {
// Make sure a segment was created.
history->QuerySegmentUsageSince(
- &consumer_, Time::Now() - TimeDelta::FromDays(1),
+ &consumer_, Time::Now() - TimeDelta::FromDays(1), 10,
NewCallback(static_cast<HistoryTest*>(this),
&HistoryTest::OnSegmentUsageAvailable));
@@ -616,7 +616,7 @@ TEST_F(HistoryTest, Segments) {
// Query again
history->QuerySegmentUsageSince(
- &consumer_, Time::Now() - TimeDelta::FromDays(1),
+ &consumer_, Time::Now() - TimeDelta::FromDays(1), 10,
NewCallback(static_cast<HistoryTest*>(this),
&HistoryTest::OnSegmentUsageAvailable));
@@ -633,7 +633,7 @@ TEST_F(HistoryTest, Segments) {
// Query again
history->QuerySegmentUsageSince(
- &consumer_, Time::Now() - TimeDelta::FromDays(1),
+ &consumer_, Time::Now() - TimeDelta::FromDays(1), 10,
NewCallback(static_cast<HistoryTest*>(this),
&HistoryTest::OnSegmentUsageAvailable));
diff --git a/chrome/browser/history/visitsegment_database.cc b/chrome/browser/history/visitsegment_database.cc
index 6bab4972..8d9c362 100644
--- a/chrome/browser/history/visitsegment_database.cc
+++ b/chrome/browser/history/visitsegment_database.cc
@@ -232,6 +232,7 @@ bool VisitSegmentDatabase::IncreaseSegmentVisitCount(SegmentID segment_id,
void VisitSegmentDatabase::QuerySegmentUsage(
const Time& from_time,
+ int max_result_count,
std::vector<PageUsageData*>* results) {
// This function gathers the highest-ranked segments in two queries.
// The first gathers scores for all segments.
@@ -241,9 +242,6 @@ void VisitSegmentDatabase::QuerySegmentUsage(
// used to lock results into position. But the rest of our code currently
// does as well.
- // How many results we return, as promised in the header file.
- const size_t kResultCount = 9;
-
// Gather all the segment scores:
SQLITE_UNIQUE_STATEMENT(statement, GetStatementCache(),
"SELECT segment_id, time_slot, visit_count "
@@ -296,8 +294,8 @@ void VisitSegmentDatabase::QuerySegmentUsage(
// Limit to the top kResultCount results.
sort(results->begin(), results->end(), PageUsageData::Predicate);
- if (results->size() > kResultCount)
- results->resize(kResultCount);
+ if (static_cast<int>(results->size()) > max_result_count)
+ results->resize(max_result_count);
// Now fetch the details about the entries we care about.
SQLITE_UNIQUE_STATEMENT(statement2, GetStatementCache(),
diff --git a/chrome/browser/history/visitsegment_database.h b/chrome/browser/history/visitsegment_database.h
index 2f2bbb2..0eb0a36f 100644
--- a/chrome/browser/history/visitsegment_database.h
+++ b/chrome/browser/history/visitsegment_database.h
@@ -49,8 +49,10 @@ class VisitSegmentDatabase {
int amount);
// Compute the segment usage since |from_time| using the provided aggregator.
- // A PageUsageData is added in |result| for the nine highest-scored segments.
+ // A PageUsageData is added in |result| for the highest-scored segments up to
+ // |max_result_count|.
void QuerySegmentUsage(const base::Time& from_time,
+ int max_result_count,
std::vector<PageUsageData*>* result);
// Delete all the segment usage data which is older than the provided time
diff --git a/chrome/browser/resources/new_tab.html b/chrome/browser/resources/new_tab.html
index e71dc51..56a0ff1 100644
--- a/chrome/browser/resources/new_tab.html
+++ b/chrome/browser/resources/new_tab.html
@@ -387,6 +387,27 @@ html[dir='rtl'] #searches input {
padding-top:4px;
font-size:8pt;
}
+.edit-visible {
+ display: none;
+}
+.edit-mode .edit-visible {
+ display: inline;
+}
+.non-edit-visible {
+ display: inline;
+}
+.edit-mode .non-edit-visible {
+ display: none;
+}
+.most-visited-container {
+ position: relative;
+ left: 0px;
+ top: 0px;
+}
+.edit-mode a.most-visited-item {
+ opacity: 0.5;
+ pointer-events: none; /* Disable clicks */
+}
</style>
</head>
<body onload="logEvent('body onload fired');"
@@ -406,7 +427,10 @@ document.addEventListener('DOMContentLoaded', handleDOMContentLoaded);
<td valign="top">
<div id="mostvisitedsection" class="section">
<div id="mostvisited" style="position:relative;">
- <div class="section-title" jscontent="mostvisited"></div>
+ <div>
+ <span class="section-title non-edit-visible" jscontent="mostvisited"></span>
+ <span class="section-title edit-visible" jseval="this.innerHTML = $this.editmodeheading;"></span>
+ </div>
<div id="mostvisitedintro" style="display:none;">
<div class="most-visited-text" style="position:absolute;" jseval="this.innerHTML = $this.mostvisitedintro;"></div>
<table>
@@ -445,6 +469,16 @@ document.addEventListener('DOMContentLoaded', handleDOMContentLoaded);
</table>
</div>
<a href="#"
+ class="manage non-edit-visible"
+ onClick="enterEditMode(); return false">
+ <span jscontent="editthumbnails"></span></a>
+ <button type="button" class="edit-visible" onClick="exitEditMode();"
+ jscontent="doneediting"></button>
+ <a href="#"
+ class="manage edit-visible"
+ onClick="restoreThumbnails(); return false">
+ <span jscontent="restorethumbnails"></span></a>
+ <a href="#"
jsvalues="href:showhistoryurl"
class="manage">
<span jscontent="showhistory"></span> &raquo;</a>
@@ -534,7 +568,8 @@ function makeMostVisitedDOM(page, number) {
*/
var root;
if (page.url) {
- root = DOM('a', {href:page.url,
+ root = DOM('a', {className:'most-visited-item',
+ href:page.url,
title:page.title});
root.addEventListener("mousedown", function(event) {
chrome.send("metrics", ["NTP_MostVisited" + number])
@@ -563,10 +598,10 @@ function makeMostVisitedDOM(page, number) {
/* The following if statement is a temporary workaround for
http://crbug.com/7252 and http://crbug.com/7697. It should be removed
before closing these bugs.
- */
+ */
if (page.direction == 'rtl') {
div_title.style.textOverflow = 'clip';
- }
+ }
if (page.title) {
div_title.appendChild(document.createTextNode(page.title));
} else {
@@ -580,13 +615,28 @@ function makeMostVisitedDOM(page, number) {
return root;
}
+/* Return the DOM element for the cross that should be displayed in edit-mode
+ over a "most visited" entry. */
+function makeCrossImageDOM(url) {
+ var cross = DOM('div', {className:'edit-cross'});
+ cross.addEventListener("mousedown", function(event) {
+ chrome.send("blacklistURLFromMostVisited", [url])}, false);
+ return cross;
+}
+
/* This function is called by the browser with the most visited pages list.
|pages| is a list of page objects, which have url, title, and direction
attributes. */
function renderMostVisitedPages(pages) {
logEvent('renderMostVisitedPages called: ' + pages.length);
- document.getElementById("main").className = 'visible';
+ var table = document.getElementById("main");
+ // If we were in edit-mode, stay in that mode as this means this is a
+ // refresh triggered by thumbnails editing.
+ if (table.className.indexOf('edit-mode') != -1)
+ table.className = 'visible edit-mode';
+ else
+ document.getElementById("main").className = 'visible';
var table = document.getElementById("mostvisitedtable");
table.innerHTML = '';
@@ -608,10 +658,11 @@ function renderMostVisitedPages(pages) {
rows[rowNum] = DOM('tr', {});
}
- var dom = makeMostVisitedDOM(page, i);
-
var cell = DOM('td');
- cell.appendChild(dom);
+ var container = DOM('div', { className: "most-visited-container"});
+ container.appendChild(makeCrossImageDOM(page.url));
+ container.appendChild(makeMostVisitedDOM(page, i));
+ cell.appendChild(container);
rows[rowNum].appendChild(cell);
@@ -709,10 +760,10 @@ function renderRecentlyBookmarked(entries) {
/* The following if statement is a temporary workaround for
http://crbug.com/7252 and http://crbug.com/7697. It should be removed
before closing these bugs.
- */
+ */
if (entry.direction == 'rtl') {
link.style.textOverflow = 'clip';
- }
+ }
link.appendChild(document.createTextNode(entry.title));
container.appendChild(link);
}
@@ -810,10 +861,10 @@ function createRecentBookmark(tagName, data) {
/* The following if statement is a temporary workaround for
http://crbug.com/7252 and http://crbug.com/7697. It should be removed
before closing these bugs.
- */
+ */
if (data.direction == 'rtl') {
link.style.textOverflow = 'clip';
- }
+ }
link.appendChild(document.createTextNode(data.title));
return link;
@@ -905,6 +956,34 @@ RecentlyClosedHoverCard.prototype.setHideTimeout_ = function() {
setTimeout(bind(this.hide_, this), 200);
};
+/**
+ * Switches to thumbnails editing mode.
+ */
+function enterEditMode() {
+ // If the cross-image in the heading has not been added yet, do it.
+ // Note that we have to insert the image node explicitly because the
+ // heading is localized and therefore set at run-time, and we need
+ // the image to be static so that it can be inlined at build-time.
+ var crossImageDiv = document.getElementById('cross-image-container');
+ if (crossImageDiv && !crossImageDiv.hasChildNodes()) {
+ var image = document.getElementById('small-cross-image');
+ image.parentNode.removeChild(image);
+ crossImageDiv.appendChild(image);
+ image.style.display = 'inline';
+ crossImageDiv.style.display = 'inline';
+ }
+ document.getElementById('main').className = 'visible edit-mode';
+}
+
+function exitEditMode() {
+ document.getElementById('main').className = 'visible';
+}
+
+function restoreThumbnails() {
+ exitEditMode();
+ chrome.send('clearMostVisitedURLsBlacklist');
+}
+
function viewLog() {
var lines = [];
var start = log[0][1];
@@ -932,5 +1011,30 @@ processData();
setTimeout(function(){document.getElementById('main').className = 'visible'},
1000);
</script>
+
+<img id="small-cross-image" style="display: none; vertical-align:middle;" alt="X"
+ src="../../app/theme/ntp_x_icon_small.png"/>
</body>
+
+<style type="text/css">
+/* This CSS code is located at the end of file so it does not slow-down the page
+ loading, as it contains inlined images.
+*/
+.edit-mode div.edit-cross {
+ position: absolute;
+ z-index: 10;
+ width: 81px;
+ height: 81px;
+ left: 60px;
+ top: 47px;
+ background: url('../../app/theme/ntp_x_icon.png');
+}
+.edit-mode div.edit-cross:hover {
+ background: url('../../app/theme/ntp_x_icon_hover.png');
+}
+.edit-mode div.edit-cross:active {
+ background: url('../../app/theme/ntp_x_icon_active.png');
+}
+</style>
+
</html>
diff --git a/chrome/common/pref_names.cc b/chrome/common/pref_names.cc
index 5adf211..77a6aff 100644
--- a/chrome/common/pref_names.cc
+++ b/chrome/common/pref_names.cc
@@ -492,4 +492,7 @@ const wchar_t kNumKeywords[] = L"user_experience_metrics.num_keywords";
const wchar_t kEnableExtensions[] = L"extensions.enabled";
const wchar_t kEnableUserScripts[] = L"extensions.user_scripts_enabled";
+// New Tab Page URLs that should not be shown as most visited thumbnails.
+const wchar_t kNTPMostVisitedURLsBlacklist[] = L"ntp.most_visited_blacklist";
+
} // namespace prefs
diff --git a/chrome/common/pref_names.h b/chrome/common/pref_names.h
index 79f8e11..a9a37ab 100644
--- a/chrome/common/pref_names.h
+++ b/chrome/common/pref_names.h
@@ -179,6 +179,8 @@ extern const wchar_t kNumKeywords[];
extern const wchar_t kEnableExtensions[];
extern const wchar_t kEnableUserScripts[];
+
+extern const wchar_t kNTPMostVisitedURLsBlacklist[];
}
#endif // CHROME_COMMON_PREF_NAMES_H_