1a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// Copyright 2013 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)
5a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "chrome/browser/sync/glue/extensions_activity_monitor.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/files/file_path.h"
89ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "base/message_loop/message_loop.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/path_service.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/values.h"
117dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "chrome/browser/chrome_notification_types.h"
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/extensions/api/bookmarks/bookmarks_api.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/chrome_paths.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_service.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/test/test_browser_thread.h"
16f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/common/extension.h"
173551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "extensions/common/manifest_constants.h"
18a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "sync/util/extensions_activity.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using extensions::Extension;
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace browser_sync {
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::BrowserThread;
283551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)namespace keys = extensions::manifest_keys;
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Create and return an extension with the given path.
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)scoped_refptr<Extension> MakeExtension(const std::string& name) {
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath path;
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &path));
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  path = path.AppendASCII(name);
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DictionaryValue value;
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  value.SetString(keys::kVersion, "1.0.0.0");
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  value.SetString(keys::kName, name);
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string error;
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<Extension> extension(Extension::Create(
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      path, extensions::Manifest::INVALID_LOCATION, value,
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      Extension::NO_FLAGS, &error));
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(error.empty());
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return extension;
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Fire a bookmarks API event from the given extension the given
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// number of times.
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <class T>
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void FireBookmarksApiEvent(
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const scoped_refptr<Extension>& extension, int repeats) {
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<T> bookmarks_function(new T());
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bookmarks_function->set_name(T::function_name());
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < repeats; i++) {
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    content::NotificationService::current()->Notify(
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        chrome::NOTIFICATION_EXTENSION_BOOKMARKS_API_INVOKED,
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        content::Source<Extension>(extension.get()),
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        content::Details<const extensions::BookmarksFunction>(
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            bookmarks_function.get()));
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class SyncChromeExtensionsActivityMonitorTest : public testing::Test {
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SyncChromeExtensionsActivityMonitorTest()
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : ui_thread_(BrowserThread::UI, &ui_loop_),
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        extension1_(MakeExtension("extension1")),
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        extension2_(MakeExtension("extension2")),
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        id1_(extension1_->id()),
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        id2_(extension2_->id()) {}
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~SyncChromeExtensionsActivityMonitorTest() {}
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
7490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  base::MessageLoop ui_loop_;
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  content::TestBrowserThread ui_thread_;
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected:
78a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ExtensionsActivityMonitor monitor_;
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<Extension> extension1_;
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<Extension> extension2_;
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // IDs of |extension{1,2}_|.
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::string& id1_;
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::string& id2_;
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// NOTE: The tests below are DISABLED because they're flaky:
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// https://code.google.com/p/chromium/issues/detail?id=172002
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Fire some mutating bookmark API events with extension 1, then fire
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// some mutating and non-mutating bookmark API events with extension
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 2.  Only the mutating events should be recorded by the
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// syncer::ExtensionsActivityMonitor.
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(SyncChromeExtensionsActivityMonitorTest, DISABLED_Basic) {
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  FireBookmarksApiEvent<extensions::BookmarksRemoveFunction>(extension1_, 1);
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  FireBookmarksApiEvent<extensions::BookmarksMoveFunction>(extension1_, 1);
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  FireBookmarksApiEvent<extensions::BookmarksUpdateFunction>(extension1_, 2);
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  FireBookmarksApiEvent<extensions::BookmarksCreateFunction>(extension1_, 3);
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  FireBookmarksApiEvent<extensions::BookmarksSearchFunction>(extension1_, 5);
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const uint32 writes_by_extension1 = 1 + 1 + 2 + 3;
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  FireBookmarksApiEvent<extensions::BookmarksRemoveTreeFunction>(
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      extension2_, 8);
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  FireBookmarksApiEvent<extensions::BookmarksGetSubTreeFunction>(
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      extension2_, 13);
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  FireBookmarksApiEvent<extensions::BookmarksGetChildrenFunction>(
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      extension2_, 21);
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  FireBookmarksApiEvent<extensions::BookmarksGetTreeFunction>(extension2_, 33);
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const uint32 writes_by_extension2 = 8;
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
110a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  syncer::ExtensionsActivity::Records results;
111a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  monitor_.GetExtensionsActivity()->GetAndClearRecords(&results);
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(2U, results.size());
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(results.find(id1_) != results.end());
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(results.find(id2_) != results.end());
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(writes_by_extension1, results[id1_].bookmark_write_count);
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(writes_by_extension2, results[id2_].bookmark_write_count);
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Fire some mutating bookmark API events with both extensions.  Then
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// get the records, fire some more mutating and non-mutating events,
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// and put the old records back.  Those should be merged with the new
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// records correctly.
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(SyncChromeExtensionsActivityMonitorTest, DISABLED_Put) {
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  FireBookmarksApiEvent<extensions::BookmarksCreateFunction>(extension1_, 5);
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  FireBookmarksApiEvent<extensions::BookmarksMoveFunction>(extension2_, 8);
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
128a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  syncer::ExtensionsActivity::Records results;
129a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  monitor_.GetExtensionsActivity()->GetAndClearRecords(&results);
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(2U, results.size());
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(5U, results[id1_].bookmark_write_count);
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(8U, results[id2_].bookmark_write_count);
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  FireBookmarksApiEvent<extensions::BookmarksGetTreeFunction>(extension2_, 3);
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  FireBookmarksApiEvent<extensions::BookmarksUpdateFunction>(extension2_, 2);
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Simulate a commit failure, which augments the active record set with the
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // refugee records.
140a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  monitor_.GetExtensionsActivity()->PutRecords(results);
141a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  syncer::ExtensionsActivity::Records new_records;
142a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  monitor_.GetExtensionsActivity()->GetAndClearRecords(&new_records);
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(2U, results.size());
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(id1_, new_records[id1_].extension_id);
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(id2_, new_records[id2_].extension_id);
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(5U, new_records[id1_].bookmark_write_count);
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(8U + 2U, new_records[id2_].bookmark_write_count);
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Fire some mutating bookmark API events and get the records multiple
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// times.  The mintor should correctly clear its records every time
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// they're returned.
1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(SyncChromeExtensionsActivityMonitorTest, DISABLED_MultiGet) {
1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  FireBookmarksApiEvent<extensions::BookmarksCreateFunction>(extension1_, 5);
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
157a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  syncer::ExtensionsActivity::Records results;
158a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  monitor_.GetExtensionsActivity()->GetAndClearRecords(&results);
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(1U, results.size());
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(5U, results[id1_].bookmark_write_count);
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
163a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  monitor_.GetExtensionsActivity()->GetAndClearRecords(&results);
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(results.empty());
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  FireBookmarksApiEvent<extensions::BookmarksCreateFunction>(extension1_, 3);
167a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  monitor_.GetExtensionsActivity()->GetAndClearRecords(&results);
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(1U, results.size());
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(3U, results[id1_].bookmark_write_count);
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace browser_sync
176