15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "components/visitedlink/browser/visitedlink_event_listener.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
77dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "base/memory/shared_memory.h"
82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "components/visitedlink/browser/visitedlink_delegate.h"
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "components/visitedlink/common/visitedlink_messages.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_service.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_types.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/render_process_host.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/render_widget_host.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::Time;
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::TimeDelta;
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::RenderWidgetHost;
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The amount of time we wait to accumulate visited link additions.
2290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)const int kCommitIntervalMs = 100;
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Size of the buffer after which individual link updates deemed not warranted
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// and the overall update should be used instead.
2690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)const unsigned kVisitedLinkBufferThreshold = 50;
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)namespace visitedlink {
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This class manages buffering and sending visited link hashes (fingerprints)
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// to renderer based on widget visibility.
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// As opposed to the VisitedLinkEventListener, which coalesces to
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// reduce the rate of messages being sent to render processes, this class
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ensures that the updates occur only when explicitly requested. This is
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// used for RenderProcessHostImpl to only send Add/Reset link events to the
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// renderers when their tabs are visible and the corresponding RenderViews are
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// created.
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class VisitedLinkUpdater {
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  explicit VisitedLinkUpdater(int render_process_id)
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : reset_needed_(false), render_process_id_(render_process_id) {
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Informs the renderer about a new visited link table.
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void SendVisitedLinkTable(base::SharedMemory* table_memory) {
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    content::RenderProcessHost* process =
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        content::RenderProcessHost::FromID(render_process_id_);
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!process)
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;  // Happens in tests
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::SharedMemoryHandle handle_for_process;
535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    table_memory->ShareReadOnlyToProcess(process->GetHandle(),
545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                         &handle_for_process);
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (base::SharedMemory::IsHandleValid(handle_for_process))
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      process->Send(new ChromeViewMsg_VisitedLink_NewTable(
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          handle_for_process));
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Buffers |links| to update, but doesn't actually relay them.
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void AddLinks(const VisitedLinkCommon::Fingerprints& links) {
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (reset_needed_)
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (pending_.size() + links.size() > kVisitedLinkBufferThreshold) {
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Once the threshold is reached, there's no need to store pending visited
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // link updates -- we opt for resetting the state for all links.
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      AddReset();
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pending_.insert(pending_.end(), links.begin(), links.end());
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Tells the updater that sending individual link updates is no longer
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // necessary and the visited state for all links should be reset.
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void AddReset() {
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    reset_needed_ = true;
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pending_.clear();
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Sends visited link update messages: a list of links whose visited state
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // changed or reset of visited state for all links.
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void Update() {
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    content::RenderProcessHost* process =
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        content::RenderProcessHost::FromID(render_process_id_);
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!process)
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;  // Happens in tests
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!process->VisibleWidgetCount())
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (reset_needed_) {
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      process->Send(new ChromeViewMsg_VisitedLink_Reset());
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      reset_needed_ = false;
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (pending_.empty())
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    process->Send(new ChromeViewMsg_VisitedLink_Add(pending_));
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pending_.clear();
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool reset_needed_;
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int render_process_id_;
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VisitedLinkCommon::Fingerprints pending_;
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)VisitedLinkEventListener::VisitedLinkEventListener(
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    VisitedLinkMaster* master,
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    content::BrowserContext* browser_context)
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : master_(master),
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      browser_context_(browser_context) {
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_CREATED,
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 content::NotificationService::AllBrowserContextsAndSources());
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_TERMINATED,
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 content::NotificationService::AllBrowserContextsAndSources());
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  registrar_.Add(this, content::NOTIFICATION_RENDER_WIDGET_VISIBILITY_CHANGED,
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 content::NotificationService::AllBrowserContextsAndSources());
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)VisitedLinkEventListener::~VisitedLinkEventListener() {
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!pending_visited_links_.empty())
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pending_visited_links_.clear();
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void VisitedLinkEventListener::NewTable(base::SharedMemory* table_memory) {
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!table_memory)
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Send to all RenderProcessHosts.
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (Updaters::iterator i = updaters_.begin(); i != updaters_.end(); ++i) {
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Make sure to not send to incognito renderers.
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    content::RenderProcessHost* process =
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        content::RenderProcessHost::FromID(i->first);
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!process)
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    i->second->SendVisitedLinkTable(table_memory);
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void VisitedLinkEventListener::Add(VisitedLinkMaster::Fingerprint fingerprint) {
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pending_visited_links_.push_back(fingerprint);
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!coalesce_timer_.IsRunning()) {
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    coalesce_timer_.Start(FROM_HERE,
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        TimeDelta::FromMilliseconds(kCommitIntervalMs), this,
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        &VisitedLinkEventListener::CommitVisitedLinks);
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void VisitedLinkEventListener::Reset() {
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pending_visited_links_.clear();
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  coalesce_timer_.Stop();
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (Updaters::iterator i = updaters_.begin(); i != updaters_.end(); ++i) {
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    i->second->AddReset();
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    i->second->Update();
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void VisitedLinkEventListener::CommitVisitedLinks() {
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Send to all RenderProcessHosts.
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (Updaters::iterator i = updaters_.begin(); i != updaters_.end(); ++i) {
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    i->second->AddLinks(pending_visited_links_);
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    i->second->Update();
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pending_visited_links_.clear();
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void VisitedLinkEventListener::Observe(
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int type,
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const content::NotificationSource& source,
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const content::NotificationDetails& details) {
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (type) {
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case content::NOTIFICATION_RENDERER_PROCESS_CREATED: {
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      content::RenderProcessHost* process =
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          content::Source<content::RenderProcessHost>(source).ptr();
1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (browser_context_ != process->GetBrowserContext())
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return;
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // Happens on browser start up.
1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (!master_->shared_memory())
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return;
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      updaters_[process->GetID()] =
1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          make_linked_ptr(new VisitedLinkUpdater(process->GetID()));
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      updaters_[process->GetID()]->SendVisitedLinkTable(
1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          master_->shared_memory());
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case content::NOTIFICATION_RENDERER_PROCESS_TERMINATED: {
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      content::RenderProcessHost* process =
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          content::Source<content::RenderProcessHost>(source).ptr();
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (updaters_.count(process->GetID())) {
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        updaters_.erase(process->GetID());
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case content::NOTIFICATION_RENDER_WIDGET_VISIBILITY_CHANGED: {
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      RenderWidgetHost* widget =
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          content::Source<RenderWidgetHost>(source).ptr();
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int child_id = widget->GetProcess()->GetID();
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (updaters_.count(child_id))
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        updaters_[child_id]->Update();
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NOTREACHED();
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
22090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}  // namespace visitedlink
221