diff --git i/chromium/components/history/content/browser/content_visit_delegate.cc w/chromium/components/history/content/browser/content_visit_delegate.cc
index 803a7b46c2..b126b8f303 100644
--- i/chromium/components/history/content/browser/content_visit_delegate.cc
+++ w/chromium/components/history/content/browser/content_visit_delegate.cc
@@ -19,23 +19,6 @@
 namespace history {
 namespace {
 
-// URLIterator from std::vector<GURL>
-class URLIteratorFromURLs : public visitedlink::VisitedLinkMaster::URLIterator {
- public:
-  explicit URLIteratorFromURLs(const std::vector<GURL>& urls)
-      : itr_(urls.begin()), end_(urls.end()) {}
-
-  // visitedlink::VisitedLinkMaster::URLIterator implementation.
-  const GURL& NextURL() override { return *(itr_++); }
-  bool HasNextURL() const override { return itr_ != end_; }
-
- private:
-  std::vector<GURL>::const_iterator itr_;
-  std::vector<GURL>::const_iterator end_;
-
-  DISALLOW_COPY_AND_ASSIGN(URLIteratorFromURLs);
-};
-
 // IterateUrlsDBTask bridge HistoryBackend::URLEnumerator to
 // visitedlink::VisitedLinkDelegate::URLEnumerator.
 class IterateUrlsDBTask : public HistoryDBTask {
@@ -108,8 +91,7 @@ void ContentVisitDelegate::AddURLs(const std::vector<GURL>& urls) {
 }
 
 void ContentVisitDelegate::DeleteURLs(const std::vector<GURL>& urls) {
-  URLIteratorFromURLs iterator(urls);
-  visitedlink_master_->DeleteURLs(&iterator);
+  visitedlink_master_->DeleteURLs(urls);
 }
 
 void ContentVisitDelegate::DeleteAllURLs() {
diff --git i/chromium/components/visitedlink/browser/visitedlink_master.cc w/chromium/components/visitedlink/browser/visitedlink_master.cc
index 0447c15a85..05459103ed 100644
--- i/chromium/components/visitedlink/browser/visitedlink_master.cc
+++ w/chromium/components/visitedlink/browser/visitedlink_master.cc
@@ -70,9 +70,14 @@ void GenerateSalt(uint8_t salt[LINK_SALT_LENGTH]) {
 }
 
 // Opens file on a background thread to not block UI thread.
-void AsyncOpen(FILE** file, const base::FilePath& filename) {
+void AsyncOpen(FILE** file, const base::FilePath& filename, time_t* file_mtime) {
   *file = base::OpenFile(filename, "wb+");
   DLOG_IF(ERROR, !(*file)) << "Failed to open file " << filename.value();
+
+  struct stat stat_buf;
+  if (fstat(fileno(*file), &stat_buf) == 0) {
+      *file_mtime = stat_buf.st_mtime;
+  }
 }
 
 // Returns true if the write was complete.
@@ -129,7 +134,8 @@ struct VisitedLinkMaster::LoadFromFileResult
                      mojo::ScopedSharedBufferMapping hash_table,
                      int32_t num_entries,
                      int32_t used_count,
-                     uint8_t salt[LINK_SALT_LENGTH]);
+                     uint8_t salt[LINK_SALT_LENGTH],
+                     time_t mtime);
 
   base::ScopedFILE file;
   mojo::ScopedSharedBufferHandle shared_memory;
@@ -137,6 +143,7 @@ struct VisitedLinkMaster::LoadFromFileResult
   int32_t num_entries;
   int32_t used_count;
   uint8_t salt[LINK_SALT_LENGTH];
+  time_t mtime;
 
  private:
   friend class base::RefCountedThreadSafe<LoadFromFileResult>;
@@ -151,12 +158,14 @@ VisitedLinkMaster::LoadFromFileResult::LoadFromFileResult(
     mojo::ScopedSharedBufferMapping hash_table,
     int32_t num_entries,
     int32_t used_count,
-    uint8_t salt[LINK_SALT_LENGTH])
+    uint8_t salt[LINK_SALT_LENGTH],
+    time_t mtime)
     : file(std::move(file)),
       shared_memory(std::move(shared_memory)),
       hash_table(std::move(hash_table)),
       num_entries(num_entries),
-      used_count(used_count) {
+      used_count(used_count),
+      mtime(mtime) {
   memcpy(this->salt, salt, LINK_SALT_LENGTH);
 }
 
@@ -279,6 +288,7 @@ VisitedLinkMaster::~VisitedLinkMaster() {
 
 void VisitedLinkMaster::InitMembers() {
   file_ = NULL;
+  file_mtime_ = 0;
   shared_memory_serial_ = 0;
   used_items_ = 0;
   table_size_override_ = 0;
@@ -362,6 +372,15 @@ void VisitedLinkMaster::PostIOTask(const tracked_objects::Location& from_here,
 }
 
 void VisitedLinkMaster::AddURL(const GURL& url) {
+  CheckFileModifiedCallback callback = base::Bind(&VisitedLinkMaster::DoAddURL, weak_ptr_factory_.GetWeakPtr(), url);
+  PostIOTask(FROM_HERE,
+             base::Bind(&VisitedLinkMaster::AsyncCheckFileModified, file_, file_mtime_, callback));
+}
+
+void VisitedLinkMaster::DoAddURL(const GURL &url, bool modified)
+{
+  if (modified)
+    ReloadFileFromDisk();
   Hash index = TryToAddURL(url);
   if (!table_builder_.get() &&
       !table_is_loading_from_file_ &&
@@ -376,6 +395,15 @@ void VisitedLinkMaster::AddURL(const GURL& url) {
 }
 
 void VisitedLinkMaster::AddURLs(const std::vector<GURL>& urls) {
+  CheckFileModifiedCallback callback = base::Bind(&VisitedLinkMaster::DoAddURLs, weak_ptr_factory_.GetWeakPtr(), urls);
+  PostIOTask(FROM_HERE,
+             base::Bind(&VisitedLinkMaster::AsyncCheckFileModified, file_, file_mtime_, callback));
+}
+
+void VisitedLinkMaster::DoAddURLs(const std::vector<GURL>& urls, bool modified)
+{
+  if (modified)
+    ReloadFileFromDisk();
   for (const GURL& url : urls) {
     Hash index = TryToAddURL(url);
     if (!table_builder_.get() &&
@@ -416,17 +444,24 @@ VisitedLinkDelegate* VisitedLinkMaster::GetDelegate() {
   return delegate_;
 }
 
-void VisitedLinkMaster::DeleteURLs(URLIterator* urls) {
-  if (!urls->HasNextURL())
+void VisitedLinkMaster::DeleteURLs(const std::vector<GURL>& urls) {
+  if (urls.empty())
     return;
 
+  CheckFileModifiedCallback callback = base::Bind(&VisitedLinkMaster::DoDeleteURLs, weak_ptr_factory_.GetWeakPtr(), urls);
+  PostIOTask(FROM_HERE,
+             base::Bind(&VisitedLinkMaster::AsyncCheckFileModified, file_, file_mtime_, callback));
+}
+
+void VisitedLinkMaster::DoDeleteURLs(const std::vector<GURL>& urls, bool modified) {
+  if (modified)
+    ReloadFileFromDisk();
   listener_->Reset(false);
 
   if (table_builder_.get() || table_is_loading_from_file_) {
     // A rebuild or load is in progress, save this deletion in the temporary
     // list so it can be added once rebuild is complete.
-    while (urls->HasNextURL()) {
-      const GURL& url(urls->NextURL());
+    for (const GURL& url : urls) {
       if (!url.is_valid())
         continue;
 
@@ -452,8 +487,7 @@ void VisitedLinkMaster::DeleteURLs(URLIterator* urls) {
 
   // Compute the deleted URLs' fingerprints and delete them
   std::set<Fingerprint> deleted_fingerprints;
-  while (urls->HasNextURL()) {
-    const GURL& url(urls->NextURL());
+  for (const GURL& url : urls) {
     if (!url.is_valid())
       continue;
     deleted_fingerprints.insert(
@@ -598,7 +632,7 @@ void VisitedLinkMaster::WriteFullTable() {
     file_ = static_cast<FILE**>(calloc(1, sizeof(*file_)));
     base::FilePath filename;
     GetDatabaseFileName(&filename);
-    PostIOTask(FROM_HERE, base::Bind(&AsyncOpen, file_, filename));
+    PostIOTask(FROM_HERE, base::Bind(&AsyncOpen, file_, filename, &file_mtime_));
   }
 
   // Write the new header.
@@ -616,6 +650,11 @@ void VisitedLinkMaster::WriteFullTable() {
 
   // The hash table may have shrunk, so make sure this is the end.
   PostIOTask(FROM_HERE, base::Bind(&AsyncTruncate, file_));
+
+  struct timeval tv;
+  if (gettimeofday(&tv, nullptr) == 0) {
+      file_mtime_ = tv.tv_sec;
+  }
 }
 
 bool VisitedLinkMaster::InitFromFile() {
@@ -677,9 +716,16 @@ bool VisitedLinkMaster::LoadApartFromFile(
     return false;
   }
 
+  // Remember modification time
+  struct stat stat_buf;
+  time_t mtime = 0;
+  if (fstat(fileno(file_closer.get()), &stat_buf) == 0) {
+      mtime = stat_buf.st_mtime;
+  }
+
   *load_from_file_result = new LoadFromFileResult(
       std::move(file_closer), std::move(shared_memory), std::move(hash_table),
-      num_entries, used_count, salt);
+      num_entries, used_count, salt, mtime);
   return true;
 }
 
@@ -739,6 +785,7 @@ void VisitedLinkMaster::OnTableLoadComplete(
   hash_table_ = GetHashTableFromMapping(hash_table_mapping_);
   table_length_ = load_from_file_result->num_entries;
   used_items_ = load_from_file_result->used_count;
+  file_mtime_ = load_from_file_result->mtime;
 
 #ifndef NDEBUG
   DebugValidate();
@@ -780,6 +827,22 @@ void VisitedLinkMaster::OnTableLoadComplete(
   listener_->Reset(true);
 }
 
+// This task executes on a background thread. This
+// prevents us from blocking the UI thread doing I/O. Double pointer to FILE
+// is used because file may still not be opened by the time of scheduling
+// the task for execution.
+void VisitedLinkMaster::AsyncCheckFileModified(FILE** file, time_t ref_mtime, const CheckFileModifiedCallback &callback) {
+    bool modified = false;
+    if (*file) {
+        struct stat stat_buf;
+        if (fstat(fileno(*file), &stat_buf) == 0) {
+            modified = ref_mtime < stat_buf.st_mtime;
+        }
+    }
+    BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+            base::Bind(callback, modified));
+}
+
 bool VisitedLinkMaster::InitFromScratch(bool suppress_rebuild) {
   if (suppress_rebuild && persist_to_disk_) {
     // When we disallow rebuilds (normally just unit tests), just use the
@@ -1108,6 +1171,17 @@ void VisitedLinkMaster::OnTableRebuildComplete(
   }
 }
 
+void VisitedLinkMaster::ReloadFileFromDisk() {
+    if (!persist_to_disk_)
+        return;
+    if (!file_)
+        return;
+    PostIOTask(FROM_HERE, base::Bind(&AsyncClose, file_));
+    // AsyncClose() will close the file and free the memory pointed by |file_|.
+    file_ = NULL;
+    InitFromFile();
+}
+
 void VisitedLinkMaster::WriteToFile(FILE** file,
                                     off_t offset,
                                     void* data,
@@ -1146,6 +1220,11 @@ void VisitedLinkMaster::WriteHashRangeToFile(Hash first_hash, Hash last_hash) {
                 &hash_table_[first_hash],
                 (last_hash - first_hash + 1) * sizeof(Fingerprint));
   }
+
+  struct timeval tv;
+  if (gettimeofday(&tv, nullptr) == 0) {
+      file_mtime_ = tv.tv_sec;
+  }
 }
 
 // static
diff --git i/chromium/components/visitedlink/browser/visitedlink_master.h w/chromium/components/visitedlink/browser/visitedlink_master.h
index 6eb50972bd..ab4803ee8c 100644
--- i/chromium/components/visitedlink/browser/visitedlink_master.h
+++ w/chromium/components/visitedlink/browser/visitedlink_master.h
@@ -115,23 +115,8 @@ class VisitedLinkMaster : public VisitedLinkCommon {
   // Adds a set of URLs to the table.
   void AddURLs(const std::vector<GURL>& urls);
 
-  // See DeleteURLs.
-  class URLIterator {
-   public:
-    // HasNextURL must return true when this is called. Returns the next URL
-    // then advances the iterator. Note that the returned reference is only
-    // valid until the next call of NextURL.
-    virtual const GURL& NextURL() = 0;
-
-    // Returns true if still has URLs to be iterated.
-    virtual bool HasNextURL() const = 0;
-
-   protected:
-    virtual ~URLIterator() {}
-  };
-
   // Deletes the specified URLs from |rows| from the table.
-  void DeleteURLs(URLIterator* iterator);
+  void DeleteURLs(const std::vector<GURL>& urls);
 
   // Clears the visited links table by deleting the file from disk. Used as
   // part of history clearing.
@@ -181,6 +166,9 @@ class VisitedLinkMaster : public VisitedLinkCommon {
       bool success,
       scoped_refptr<LoadFromFileResult> load_from_file_result)>;
 
+  using CheckFileModifiedCallback = base::Callback<void(
+      bool modified)>;
+
   // Object to rebuild the table on the history thread (see the .cc file).
   class TableBuilder;
 
@@ -237,6 +225,9 @@ class VisitedLinkMaster : public VisitedLinkCommon {
   static void LoadFromFile(const base::FilePath& filename,
                            const TableLoadCompleteCallback& callback);
 
+  // Called in the background thread
+  static void AsyncCheckFileModified(FILE** file, time_t ref_mtime, const CheckFileModifiedCallback &callback);
+
   // Load the table from the database file. Returns true on success.
   // Fills parameter |load_from_file_result| on success. It is called from
   // the background thread.
@@ -250,6 +241,12 @@ class VisitedLinkMaster : public VisitedLinkCommon {
       bool success,
       scoped_refptr<LoadFromFileResult> load_from_file_result);
 
+  // These are called from the background thread and executed on the UI
+  // thread.
+  void DoAddURL(const GURL& urls, bool modified);
+  void DoAddURLs(const std::vector<GURL>& urls, bool modified);
+  void DoDeleteURLs(const std::vector<GURL>& urls, bool modified);
+
   // Reads the header of the link coloring database from disk. Assumes the
   // file pointer is at the beginning of the file and that it is the first
   // asynchronous I/O operation on the background thread.
@@ -265,6 +262,9 @@ class VisitedLinkMaster : public VisitedLinkCommon {
   // Fills *filename with the name of the link database filename
   bool GetDatabaseFileName(base::FilePath* filename);
 
+  // Reload file from disk because another process changed it.
+  void ReloadFileFromDisk();
+
   // Wrapper around Window's WriteFile using asynchronous I/O. This will proxy
   // the write to a background thread.
   void WriteToFile(FILE** hfile, off_t offset, void* data, int32_t data_size);
@@ -436,6 +436,8 @@ class VisitedLinkMaster : public VisitedLinkCommon {
   // by |*file_|.
   FILE** file_;
 
+  time_t file_mtime_;
+
   // If true, will try to persist the hash table to disk. Will rebuild from
   // VisitedLinkDelegate::RebuildTable if there are disk corruptions.
   bool persist_to_disk_;
@@ -497,6 +499,7 @@ inline void VisitedLinkMaster::DebugValidate() {
       used_count++;
   }
   DCHECK_EQ(used_count, used_items_);
+  printf("used_items_=%d\n", used_items_);
 }
 #endif
 
