1// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "components/visitedlink/renderer/visitedlink_slave.h"
6
7#include "base/logging.h"
8#include "base/memory/shared_memory.h"
9#include "components/visitedlink/common/visitedlink_messages.h"
10#include "third_party/WebKit/public/web/WebView.h"
11
12using blink::WebView;
13
14namespace visitedlink {
15
16VisitedLinkSlave::VisitedLinkSlave() : shared_memory_(NULL) {}
17
18VisitedLinkSlave::~VisitedLinkSlave() {
19  FreeTable();
20}
21
22bool VisitedLinkSlave::OnControlMessageReceived(const IPC::Message& message) {
23  bool handled = true;
24  IPC_BEGIN_MESSAGE_MAP(VisitedLinkSlave, message)
25    IPC_MESSAGE_HANDLER(ChromeViewMsg_VisitedLink_NewTable,
26                        OnUpdateVisitedLinks)
27    IPC_MESSAGE_HANDLER(ChromeViewMsg_VisitedLink_Add, OnAddVisitedLinks)
28    IPC_MESSAGE_HANDLER(ChromeViewMsg_VisitedLink_Reset, OnResetVisitedLinks)
29    IPC_MESSAGE_UNHANDLED(handled = false)
30  IPC_END_MESSAGE_MAP()
31  return handled;
32}
33
34// This function's job is to initialize the table with the given
35// shared memory handle. This memory is mapped into the process.
36void VisitedLinkSlave::OnUpdateVisitedLinks(base::SharedMemoryHandle table) {
37  DCHECK(base::SharedMemory::IsHandleValid(table)) << "Bad table handle";
38  // since this function may be called again to change the table, we may need
39  // to free old objects
40  FreeTable();
41  DCHECK(shared_memory_ == NULL && hash_table_ == NULL);
42
43  // create the shared memory object
44  shared_memory_ = new base::SharedMemory(table, true);
45  if (!shared_memory_)
46    return;
47
48  // map the header into our process so we can see how long the rest is,
49  // and set the salt
50  if (!shared_memory_->Map(sizeof(SharedHeader)))
51    return;
52  SharedHeader* header =
53    static_cast<SharedHeader*>(shared_memory_->memory());
54  DCHECK(header);
55  int32 table_len = header->length;
56  memcpy(salt_, header->salt, sizeof(salt_));
57  shared_memory_->Unmap();
58
59  // now do the whole table because we know the length
60  if (!shared_memory_->Map(sizeof(SharedHeader) +
61                          table_len * sizeof(Fingerprint))) {
62    shared_memory_->Close();
63    return;
64  }
65
66  // commit the data
67  DCHECK(shared_memory_->memory());
68  hash_table_ = reinterpret_cast<Fingerprint*>(
69      static_cast<char*>(shared_memory_->memory()) + sizeof(SharedHeader));
70  table_length_ = table_len;
71}
72
73void VisitedLinkSlave::OnAddVisitedLinks(
74    const VisitedLinkSlave::Fingerprints& fingerprints) {
75  for (size_t i = 0; i < fingerprints.size(); ++i)
76    WebView::updateVisitedLinkState(fingerprints[i]);
77}
78
79void VisitedLinkSlave::OnResetVisitedLinks() {
80  WebView::resetVisitedLinkState();
81}
82
83void VisitedLinkSlave::FreeTable() {
84  if (shared_memory_) {
85    delete shared_memory_;
86    shared_memory_ = NULL;
87  }
88  hash_table_ = NULL;
89  table_length_ = 0;
90}
91
92}  // namespace visitedlink
93