Persist visited link status (issue #287)

This commit is contained in:
Marshall Greenblatt 2016-01-11 19:19:51 -05:00
parent 6d7ee1e084
commit 63d313de76
14 changed files with 179 additions and 7 deletions

View File

@ -900,6 +900,9 @@
'<(DEPTH)/components/components.gyp:update_client',
'<(DEPTH)/components/components.gyp:user_prefs',
'<(DEPTH)/components/components.gyp:version_info',
'<(DEPTH)/components/components.gyp:visitedlink_browser',
'<(DEPTH)/components/components.gyp:visitedlink_common',
'<(DEPTH)/components/components.gyp:visitedlink_renderer',
'<(DEPTH)/components/components.gyp:web_cache_renderer',
'<(DEPTH)/components/url_formatter/url_formatter.gyp:url_formatter',
'<(DEPTH)/content/content.gyp:content_app_both',

View File

@ -152,6 +152,10 @@ class CefBrowserContext
// Settings for plugins and extensions.
virtual HostContentSettingsMap* GetHostContentSettingsMap() = 0;
// Called from CefBrowserHostImpl::DidNavigateAnyFrame to update the table of
// visited links.
virtual void AddVisitedURLs(const std::vector<GURL>& urls) = 0;
CefResourceContext* resource_context() const {
return resource_context_.get();
}

View File

@ -30,6 +30,8 @@
#include "components/content_settings/core/browser/host_content_settings_map.h"
#include "components/guest_view/browser/guest_view_manager.h"
#include "components/ui/zoom/zoom_event_manager.h"
#include "components/visitedlink/browser/visitedlink_event_listener.h"
#include "components/visitedlink/browser/visitedlink_master.h"
#include "content/public/browser/download_manager.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/storage_partition.h"
@ -129,6 +131,69 @@ base::LazyInstance<ImplManager> g_manager = LAZY_INSTANCE_INITIALIZER;
} // namespace
// Creates and manages VisitedLinkEventListener objects for each
// CefBrowserContext sharing the same VisitedLinkMaster.
class CefVisitedLinkListener : public visitedlink::VisitedLinkMaster::Listener {
public:
CefVisitedLinkListener()
: master_(nullptr) {
}
void set_master(visitedlink::VisitedLinkMaster* master) {
DCHECK(!master_);
master_ = master;
}
void CreateListenerForContext(const CefBrowserContext* context) {
CEF_REQUIRE_UIT();
scoped_ptr<visitedlink::VisitedLinkEventListener> listener(
new visitedlink::VisitedLinkEventListener(
master_, const_cast<CefBrowserContext*>(context)));
listener_map_.insert(std::make_pair(context, std::move(listener)));
}
void RemoveListenerForContext(const CefBrowserContext* context) {
CEF_REQUIRE_UIT();
ListenerMap::iterator it = listener_map_.find(context);
DCHECK(it != listener_map_.end());
listener_map_.erase(it);
}
// visitedlink::VisitedLinkMaster::Listener methods.
void NewTable(base::SharedMemory* shared_memory) override {
CEF_REQUIRE_UIT();
ListenerMap::iterator it = listener_map_.begin();
for (; it != listener_map_.end(); ++it)
it->second->NewTable(shared_memory);
}
void Add(visitedlink::VisitedLinkCommon::Fingerprint fingerprint) override {
CEF_REQUIRE_UIT();
ListenerMap::iterator it = listener_map_.begin();
for (; it != listener_map_.end(); ++it)
it->second->Add(fingerprint);
}
void Reset(bool invalidate_hashes) override {
CEF_REQUIRE_UIT();
ListenerMap::iterator it = listener_map_.begin();
for (; it != listener_map_.end(); ++it)
it->second->Reset(invalidate_hashes);
}
private:
visitedlink::VisitedLinkMaster* master_;
// Map of CefBrowserContext to the associated VisitedLinkEventListener.
typedef std::map<const CefBrowserContext*,
scoped_ptr<visitedlink::VisitedLinkEventListener> >
ListenerMap;
ListenerMap listener_map_;
DISALLOW_COPY_AND_ASSIGN(CefVisitedLinkListener);
};
CefBrowserContextImpl::CefBrowserContextImpl(
const CefRequestContextSettings& settings)
: settings_(settings) {
@ -183,6 +248,19 @@ void CefBrowserContextImpl::Initialize() {
pref_path = cache_path_.AppendASCII(browser_prefs::kUserPrefsFileName);
pref_service_ = browser_prefs::CreatePrefService(pref_path);
// Initialize visited links management.
base::FilePath visited_link_path;
if (!cache_path_.empty())
visited_link_path = cache_path_.Append(FILE_PATH_LITERAL("Visited Links"));
visitedlink_listener_ = new CefVisitedLinkListener;
visitedlink_master_.reset(
new visitedlink::VisitedLinkMaster(visitedlink_listener_, this,
!visited_link_path.empty(), false,
visited_link_path, 0));
visitedlink_listener_->set_master(visitedlink_master_.get());
visitedlink_listener_->CreateListenerForContext(this);
visitedlink_master_->Init();
CefBrowserContext::Initialize();
// Initialize proxy configuration tracker.
@ -202,10 +280,15 @@ void CefBrowserContextImpl::AddProxy(const CefBrowserContextProxy* proxy) {
CEF_REQUIRE_UIT();
DCHECK(!HasProxy(proxy));
proxy_list_.push_back(proxy);
visitedlink_listener_->CreateListenerForContext(proxy);
}
void CefBrowserContextImpl::RemoveProxy(const CefBrowserContextProxy* proxy) {
CEF_REQUIRE_UIT();
visitedlink_listener_->RemoveListenerForContext(proxy);
bool found = false;
ProxyList::iterator it = proxy_list_.begin();
for (; it != proxy_list_.end(); ++it) {
@ -412,3 +495,13 @@ HostContentSettingsMap* CefBrowserContextImpl::GetHostContentSettingsMap() {
}
return host_content_settings_map_.get();
}
void CefBrowserContextImpl::AddVisitedURLs(const std::vector<GURL>& urls) {
visitedlink_master_->AddURLs(urls);
}
void CefBrowserContextImpl::RebuildTable(
const scoped_refptr<URLEnumerator>& enumerator) {
// Called when visited links will not or cannot be loaded from disk.
enumerator->OnComplete(true);
}

View File

@ -14,16 +14,23 @@
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "components/proxy_config/pref_proxy_config_tracker.h"
#include "components/visitedlink/browser/visitedlink_delegate.h"
class CefBrowserContextProxy;
class CefDownloadManagerDelegate;
class CefSSLHostStateDelegate;
class CefVisitedLinkListener;
namespace visitedlink {
class VisitedLinkMaster;
}
// Isolated BrowserContext implementation. Life span is controlled by
// CefRequestContextImpl and (for the main context) CefBrowserMainParts. Only
// accessed on the UI thread unless otherwise indicated. See browser_context.h
// for an object relationship diagram.
class CefBrowserContextImpl : public CefBrowserContext {
class CefBrowserContextImpl : public CefBrowserContext,
public visitedlink::VisitedLinkDelegate {
public:
explicit CefBrowserContextImpl(const CefRequestContextSettings& settings);
@ -88,6 +95,10 @@ class CefBrowserContextImpl : public CefBrowserContext {
content::URLRequestInterceptorScopedVector request_interceptors)
override;
HostContentSettingsMap* GetHostContentSettingsMap() override;
void AddVisitedURLs(const std::vector<GURL>& urls) override;
// visitedlink::VisitedLinkDelegate methods.
void RebuildTable(const scoped_refptr<URLEnumerator>& enumerator) override;
// Guaranteed to exist once this object has been initialized.
scoped_refptr<CefURLRequestContextGetterImpl> request_context() const {
@ -118,6 +129,9 @@ class CefBrowserContextImpl : public CefBrowserContext {
scoped_ptr<content::PermissionManager> permission_manager_;
scoped_ptr<CefSSLHostStateDelegate> ssl_host_state_delegate_;
scoped_refptr<HostContentSettingsMap> host_content_settings_map_;
scoped_ptr<visitedlink::VisitedLinkMaster> visitedlink_master_;
// |visitedlink_listener_| is owned by visitedlink_master_.
CefVisitedLinkListener* visitedlink_listener_;
DISALLOW_COPY_AND_ASSIGN(CefBrowserContextImpl);
};

View File

@ -12,6 +12,7 @@
#include "base/logging.h"
#include "chrome/browser/font_family_cache.h"
#include "components/guest_view/common/guest_view_constants.h"
#include "components/visitedlink/browser/visitedlink_master.h"
#include "content/browser/streams/stream_context.h"
#include "content/public/browser/storage_partition.h"
@ -196,3 +197,7 @@ net::URLRequestContextGetter*
HostContentSettingsMap* CefBrowserContextProxy::GetHostContentSettingsMap() {
return parent_->GetHostContentSettingsMap();
}
void CefBrowserContextProxy::AddVisitedURLs(const std::vector<GURL>& urls) {
parent_->AddVisitedURLs(urls);
}

View File

@ -70,6 +70,7 @@ class CefBrowserContextProxy : public CefBrowserContext {
content::URLRequestInterceptorScopedVector request_interceptors)
override;
HostContentSettingsMap* GetHostContentSettingsMap() override;
void AddVisitedURLs(const std::vector<GURL>& urls) override;
scoped_refptr<CefBrowserContextImpl> parent() const {
return parent_;

View File

@ -2403,6 +2403,21 @@ void CefBrowserHostImpl::FrameDeleted(
focused_frame_id_ = CefFrameHostImpl::kInvalidFrameId;
}
void CefBrowserHostImpl::DidNavigateAnyFrame(
content::RenderFrameHost* render_frame_host,
const content::LoadCommittedDetails& details,
const content::FrameNavigateParams& params) {
if (!web_contents())
return;
scoped_refptr<CefBrowserContext> context =
static_cast<CefBrowserContext*>(web_contents()->GetBrowserContext());
if (!context.get())
return;
context->AddVisitedURLs(params.redirects);
}
void CefBrowserHostImpl::TitleWasSet(content::NavigationEntry* entry,
bool explicit_set) {
// |entry| may be NULL if a popup is created via window.open and never

View File

@ -406,6 +406,10 @@ class CefBrowserHostImpl : public CefBrowserHost,
bool was_ignored_by_handler) override;
void FrameDeleted(
content::RenderFrameHost* render_frame_host) override;
void DidNavigateAnyFrame(
content::RenderFrameHost* render_frame_host,
const content::LoadCommittedDetails& details,
const content::FrameNavigateParams& params) override;
void TitleWasSet(content::NavigationEntry* entry, bool explicit_set) override;
void PluginCrashed(const base::FilePath& plugin_path,
base::ProcessId plugin_pid) override;

View File

@ -50,6 +50,7 @@
#include "components/content_settings/core/common/content_settings_types.h"
#include "components/nacl/common/nacl_constants.h"
#include "components/printing/renderer/print_web_view_helper.h"
#include "components/visitedlink/renderer/visitedlink_slave.h"
#include "components/web_cache/renderer/web_cache_render_process_observer.h"
#include "content/common/frame_messages.h"
#include "content/public/browser/browser_thread.h"
@ -391,6 +392,9 @@ void CefContentRendererClient::RenderThreadStarted() {
thread->AddObserver(spellcheck_.get());
}
visited_link_slave_.reset(new visitedlink::VisitedLinkSlave());
thread->AddObserver(visited_link_slave_.get());
if (content::RenderProcessHost::run_renderer_in_process()) {
// When running in single-process mode register as a destruction observer
// on the render thread's MessageLoop.
@ -596,6 +600,15 @@ bool CefContentRendererClient::WillSendRequest(
return false;
}
unsigned long long CefContentRendererClient::VisitedLinkHash(
const char* canonical_url, size_t length) {
return visited_link_slave_->ComputeURLFingerprint(canonical_url, length);
}
bool CefContentRendererClient::IsLinkVisited(unsigned long long link_hash) {
return visited_link_slave_->IsVisited(link_hash);
}
content::BrowserPluginDelegate*
CefContentRendererClient::CreateBrowserPluginDelegate(
content::RenderFrame* render_frame,

View File

@ -30,6 +30,10 @@ class ExtensionsRendererClient;
class ResourceRequestPolicy;
}
namespace visitedlink {
class VisitedLinkSlave;
}
namespace web_cache {
class WebCacheRenderProcessObserver;
}
@ -116,6 +120,9 @@ class CefContentRendererClient : public content::ContentRendererClient,
const GURL& url,
const GURL& first_party_for_cookies,
GURL* new_url) override;
unsigned long long VisitedLinkHash(const char* canonical_url,
size_t length) override;
bool IsLinkVisited(unsigned long long link_hash) override;
content::BrowserPluginDelegate* CreateBrowserPluginDelegate(
content::RenderFrame* render_frame,
const std::string& mime_type,
@ -145,6 +152,7 @@ class CefContentRendererClient : public content::ContentRendererClient,
scoped_ptr<CefRenderProcessObserver> observer_;
scoped_ptr<web_cache::WebCacheRenderProcessObserver> web_cache_observer_;
scoped_ptr<SpellCheck> spellcheck_;
scoped_ptr<visitedlink::VisitedLinkSlave> visited_link_slave_;
// Map of RenderView pointers to CefBrowserImpl references.
typedef std::map<content::RenderView*, CefRefPtr<CefBrowserImpl> > BrowserMap;

View File

@ -49,6 +49,8 @@ RootWindowManager::RootWindowManager(bool terminate_when_all_windows_closed)
DCHECK(command_line.get());
request_context_per_browser_ =
command_line->HasSwitch(switches::kRequestContextPerBrowser);
request_context_shared_cache_ =
command_line->HasSwitch(switches::kRequestContextSharedCache);
}
RootWindowManager::~RootWindowManager() {
@ -147,12 +149,19 @@ CefRefPtr<CefRequestContext> RootWindowManager::GetRequestContext(
CefRefPtr<CefCommandLine> command_line =
CefCommandLine::GetGlobalCommandLine();
if (command_line->HasSwitch(switches::kCachePath)) {
// If a global cache path value is specified then give each browser a
// unique cache path.
std::stringstream ss;
ss << command_line->GetSwitchValue(switches::kCachePath).ToString() <<
time(NULL);
CefString(&settings.cache_path) = ss.str();
if (request_context_shared_cache_) {
// Give each browser the same cache path. The resulting context objects
// will share the same storage internally.
CefString(&settings.cache_path) =
command_line->GetSwitchValue(switches::kCachePath);
} else {
// Give each browser a unique cache path. This will create completely
// isolated context objects.
std::stringstream ss;
ss << command_line->GetSwitchValue(switches::kCachePath).ToString() <<
time(NULL);
CefString(&settings.cache_path) = ss.str();
}
}
return CefRequestContext::CreateContext(settings,

View File

@ -72,6 +72,7 @@ class RootWindowManager : public RootWindow::Delegate {
const bool terminate_when_all_windows_closed_;
bool request_context_per_browser_;
bool request_context_shared_cache_;
// Existing root windows. Only accessed on the main thread.
typedef std::set<scoped_refptr<RootWindow> > RootWindowSet;

View File

@ -26,6 +26,7 @@ const char kTransparentPaintingEnabled[] = "transparent-painting-enabled";
const char kShowUpdateRect[] = "show-update-rect";
const char kMouseCursorChangeDisabled[] = "mouse-cursor-change-disabled";
const char kRequestContextPerBrowser[] = "request-context-per-browser";
const char kRequestContextSharedCache[] = "request-context-shared-cache";
const char kBackgroundColor[] = "background-color";
const char kEnableGPU[] = "enable-gpu";
const char kFilterURL[] = "filter-url";

View File

@ -20,6 +20,7 @@ extern const char kTransparentPaintingEnabled[];
extern const char kShowUpdateRect[];
extern const char kMouseCursorChangeDisabled[];
extern const char kRequestContextPerBrowser[];
extern const char kRequestContextSharedCache[];
extern const char kBackgroundColor[];
extern const char kEnableGPU[];
extern const char kFilterURL[];