{"action":"created","comment":{"url":"https://api.github.com/repos/brave/brave-core/pulls/comments/239246315","pull_request_review_id":181984664,"id":239246315,"node_id":"MDI0OlB1bGxSZXF1ZXN0UmV2aWV3Q29tbWVudDIzOTI0NjMxNQ==","diff_hunk":"@@ -0,0 +1,933 @@\n+/* This Source Code Form is subject to the terms of the Mozilla Public\n+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,\n+ * You can obtain one at http://mozilla.org/MPL/2.0/. */\n+\n+#include \"brave/components/brave_ads/browser/ads_service_impl.h\"\n+\n+#include \"base/command_line.h\"\n+#include \"base/files/file_util.h\"\n+#include \"base/files/important_file_writer.h\"\n+#include \"base/guid.h\"\n+#include \"base/logging.h\"\n+#include \"base/memory/ptr_util.h\"\n+#include \"base/sequenced_task_runner.h\"\n+#include \"base/task_runner_util.h\"\n+#include \"base/task/post_task.h\"\n+#include \"bat/ads/notification_info.h\"\n+#include \"bat/ads/notification_result_type.h\"\n+#include \"bat/ads/resources/grit/bat_ads_resources.h\"\n+#include \"brave/components/brave_ads/browser/ad_notification.h\"\n+#include \"brave/components/brave_ads/browser/bundle_state_database.h\"\n+#include \"brave/components/brave_ads/common/pref_names.h\"\n+#include \"brave/components/brave_ads/common/switches.h\"\n+#include \"brave/components/services/bat_ads/public/cpp/ads_client_mojo_bridge.h\"\n+#include \"brave/components/services/bat_ads/public/interfaces/bat_ads.mojom.h\"\n+#include \"chrome/browser/browser_process.h\"\n+#include \"chrome/browser/notifications/notification_display_service.h\"\n+#include \"chrome/browser/notifications/notification_display_service_impl.h\"\n+#include \"chrome/browser/notifications/notification_handler.h\"\n+#include \"chrome/browser/profiles/profile.h\"\n+#include \"chrome/browser/ui/browser.h\"\n+#include \"chrome/browser/ui/browser_finder.h\"\n+#include \"chrome/browser/ui/browser_navigator_params.h\"\n+#include \"chrome/common/buildflags.h\"\n+#include \"chrome/common/chrome_constants.h\"\n+#include \"components/prefs/pref_service.h\"\n+#include \"components/wifi/wifi_service.h\"\n+#include \"content/public/browser/browser_thread.h\"\n+#include \"content/public/common/service_manager_connection.h\"\n+#include \"net/url_request/url_fetcher.h\"\n+#include \"services/service_manager/public/cpp/connector.h\"\n+#include \"third_party/dom_distiller_js/dom_distiller.pb.h\"\n+#include \"ui/base/l10n/l10n_util.h\"\n+#include \"ui/base/resource/resource_bundle.h\"\n+#include \"ui/message_center/public/cpp/notification.h\"\n+\n+#if defined(OS_ANDROID)\n+#include \"chrome/browser/ui/android/tab_model/tab_model_list.h\"\n+#include \"net/android/network_library.h\"\n+#endif\n+\n+namespace brave_ads {\n+\n+class LogStreamImpl : public ads::LogStream {\n+ public:\n+  LogStreamImpl(const char* file,\n+                int line,\n+                const ads::LogLevel log_level) {\n+    switch(log_level) {\n+      case ads::LogLevel::LOG_INFO:\n+        log_message_ = std::make_unique<logging::LogMessage>(file, line, logging::LOG_INFO);\n+        break;\n+      case ads::LogLevel::LOG_WARNING:\n+        log_message_ = std::make_unique<logging::LogMessage>(file, line, logging::LOG_WARNING);\n+        break;\n+      default:\n+        log_message_ = std::make_unique<logging::LogMessage>(file, line, logging::LOG_ERROR);\n+    }\n+  }\n+\n+  std::ostream& stream() override {\n+    return log_message_->stream();\n+  }\n+\n+ private:\n+  std::unique_ptr<logging::LogMessage> log_message_;\n+\n+  DISALLOW_COPY_AND_ASSIGN(LogStreamImpl);\n+};\n+\n+class AdsNotificationHandler : public NotificationHandler {\n+ public:\n+  AdsNotificationHandler(AdsServiceImpl* ads_service) :\n+      ads_service_(ads_service->AsWeakPtr()) {}\n+\n+  ~AdsNotificationHandler() override {}\n+\n+  // NotificationHandler implementation.\n+  void OnShow(Profile* profile,\n+              const std::string& notification_id) override {\n+    if (ads_service_)\n+      ads_service_->OnShow(profile, notification_id);\n+  }\n+\n+  void OnClose(Profile* profile,\n+               const GURL& origin,\n+               const std::string& notification_id,\n+               bool by_user,\n+               base::OnceClosure completed_closure) override {\n+    if (!ads_service_) {\n+      std::move(completed_closure).Run();\n+      return;\n+    }\n+\n+    ads_service_->OnClose(\n+        profile, origin, notification_id, by_user,\n+        std::move(completed_closure));\n+  }\n+\n+  void DisableNotifications(Profile* profile,\n+                            const GURL& origin) override {}\n+\n+\n+  void OpenSettings(Profile* profile, const GURL& origin) override {\n+    if (ads_service_)\n+      ads_service_->OpenSettings(profile, origin);\n+  }\n+\n+ private:\n+  base::WeakPtr<AdsServiceImpl> ads_service_;\n+\n+  DISALLOW_COPY_AND_ASSIGN(AdsNotificationHandler);\n+};\n+\n+namespace {\n+\n+void Noop() {}\n+\n+int32_t ToMojomNotificationResultInfoResultType(\n+    ads::NotificationResultInfoResultType result_type) {\n+  return (int32_t)result_type;\n+}\n+\n+static std::map<std::string, int> g_schema_resource_ids = {\n+  {\"catalog\", IDR_ADS_CATALOG_SCHEMA},\n+  {\"bundle\", IDR_ADS_BUNDLE_SCHEMA},\n+};\n+\n+int GetSchemaResourceId(const std::string& name) {\n+  if (g_schema_resource_ids.find(name) != g_schema_resource_ids.end())\n+    return g_schema_resource_ids[name];\n+\n+  NOTREACHED();\n+  return 0;\n+}\n+\n+static std::map<std::string, int> g_user_model_resource_ids = {\n+  {\"de\", IDR_ADS_USER_MODEL_DE},\n+  {\"fr\", IDR_ADS_USER_MODEL_FR},\n+  {\"en\", IDR_ADS_USER_MODEL_EN},\n+};\n+\n+int GetUserModelResourceId(const std::string& locale) {\n+  if (g_user_model_resource_ids.find(locale) != g_user_model_resource_ids.end())\n+    return g_user_model_resource_ids[locale];\n+\n+  NOTREACHED();\n+  return 0;\n+}\n+\n+net::URLFetcher::RequestType URLMethodToRequestType(\n+    ads::URLRequestMethod method) {\n+  switch(method) {\n+    case ads::URLRequestMethod::GET:\n+      return net::URLFetcher::RequestType::GET;\n+    case ads::URLRequestMethod::POST:\n+      return net::URLFetcher::RequestType::POST;\n+    case ads::URLRequestMethod::PUT:\n+      return net::URLFetcher::RequestType::PUT;\n+    default:\n+      NOTREACHED();\n+      return net::URLFetcher::RequestType::GET;\n+  }\n+}\n+\n+void EnsureBaseDirectoryExists(const base::FilePath& path) {\n+  if (!DirectoryExists(path))\n+    base::CreateDirectory(path);\n+}\n+\n+void PostWriteCallback(\n+    const base::Callback<void(bool success)>& callback,\n+    scoped_refptr<base::SequencedTaskRunner> reply_task_runner,\n+    bool success) {\n+  // We can't run |callback| on the current thread. Bounce back to\n+  // the |reply_task_runner| which is the correct sequenced thread.\n+  reply_task_runner->PostTask(FROM_HERE,\n+                              base::Bind(callback, success));\n+}\n+\n+std::string LoadOnFileTaskRunner(\n+    const base::FilePath& path) {\n+  std::string data;\n+  bool success = base::ReadFileToString(path, &data);\n+\n+  // Make sure the file isn't empty.\n+  if (!success || data.empty()) {\n+    LOG(ERROR) << \"Failed to read file: \" << path.MaybeAsASCII();\n+    return std::string();\n+  }\n+  return data;\n+}\n+\n+std::vector<ads::AdInfo> GetAdsForCategoryOnFileTaskRunner(\n+    const std::string category,\n+    BundleStateDatabase* backend) {\n+  std::vector<ads::AdInfo> ads;\n+  if (!backend)\n+    return ads;\n+\n+  backend->GetAdsForCategory(category, ads);\n+\n+  return ads;\n+}\n+\n+bool ResetOnFileTaskRunner(\n+    const base::FilePath& path) {\n+  return base::DeleteFile(path, false);\n+}\n+\n+bool SaveBundleStateOnFileTaskRunner(\n+    std::unique_ptr<ads::BundleState> bundle_state,\n+    BundleStateDatabase* backend) {\n+  if (backend && backend->SaveBundleState(*bundle_state))\n+    return true;\n+\n+  return false;\n+}\n+\n+}\n+\n+AdsServiceImpl::AdsServiceImpl(Profile* profile) :\n+    profile_(profile),\n+    file_task_runner_(base::CreateSequencedTaskRunnerWithTraits(\n+          {base::MayBlock(), base::TaskPriority::BEST_EFFORT,\n+           base::TaskShutdownBehavior::BLOCK_SHUTDOWN})),\n+    base_path_(profile_->GetPath().AppendASCII(\"ads_service\")),\n+    next_timer_id_(0),\n+    bundle_state_backend_(\n+        new BundleStateDatabase(base_path_.AppendASCII(\"bundle_state\"))),\n+    display_service_(NotificationDisplayService::GetForProfile(profile_)),\n+    enabled_(false),\n+#if !defined(OS_ANDROID)\n+    last_idle_state_(ui::IdleState::IDLE_STATE_ACTIVE),\n+    is_foreground_(!!chrome::FindBrowserWithActiveWindow()),\n+#endif\n+    bat_ads_client_binding_(new bat_ads::AdsClientMojoBridge(this)) {\n+  DCHECK(!profile_->IsOffTheRecord());\n+\n+  file_task_runner_->PostTask(FROM_HERE,\n+      base::BindOnce(&EnsureBaseDirectoryExists, base_path_));\n+  profile_pref_change_registrar_.Init(profile_->GetPrefs());\n+  profile_pref_change_registrar_.Add(\n+      prefs::kBraveAdsEnabled,\n+      base::Bind(&AdsServiceImpl::OnPrefsChanged,\n+                 base::Unretained(this)));\n+  profile_pref_change_registrar_.Add(\n+      prefs::kBraveAdsIdleThreshold,\n+      base::Bind(&AdsServiceImpl::OnPrefsChanged,\n+                 base::Unretained(this)));\n+\n+  auto* display_service_impl =\n+      static_cast<NotificationDisplayServiceImpl*>(display_service_);\n+\n+  display_service_impl->AddNotificationHandler(\n+      NotificationHandler::Type::BRAVE_ADS,\n+      std::make_unique<AdsNotificationHandler>(this));\n+\n+  if (is_enabled())\n+    Start();\n+  else\n+    Stop();\n+}\n+\n+AdsServiceImpl::~AdsServiceImpl() {\n+  file_task_runner_->DeleteSoon(FROM_HERE, bundle_state_backend_.release());\n+}\n+\n+void AdsServiceImpl::OnInitialize() {\n+  enabled_ = true;\n+  ResetTimer();\n+}\n+\n+void AdsServiceImpl::OnCreate() {\n+  if (!bat_ads_.is_bound()) {\n+    // TODO(bridiver) - reconnect?\n+    return;\n+  }\n+\n+  bat_ads_->Initialize(\n+      base::BindOnce(&AdsServiceImpl::OnInitialize, AsWeakPtr()));\n+}\n+\n+void ConnectionClosed() {\n+  // TODO(bridiver)\n+}\n+\n+void AdsServiceImpl::Start() {\n+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);\n+  DCHECK(is_enabled());\n+  DCHECK(!bat_ads_.is_bound());\n+\n+  bat_ads::mojom::BatAdsClientAssociatedPtrInfo client_ptr_info;\n+  bat_ads_client_binding_.Bind(mojo::MakeRequest(&client_ptr_info));\n+\n+  content::ServiceManagerConnection* connection =\n+      content::ServiceManagerConnection::GetForProcess();\n+\n+  if (!connection)\n+    return;\n+\n+  connection->GetConnector()->BindInterface(\n+      bat_ads::mojom::kServiceName, &bat_ads_service_);\n+\n+  bat_ads_service_.set_connection_error_handler(\n+      base::Bind(&ConnectionClosed));\n+\n+  bool is_production = false;\n+#if defined(OFFICIAL_BUILD)\n+  is_production = true;\n+#endif\n+  bool is_debug = true;\n+#if defined(NDEBUG)\n+  is_debug = false;\n+#endif\n+  bool is_testing = false;\n+\n+  const base::CommandLine& command_line =\n+      *base::CommandLine::ForCurrentProcess();\n+\n+  if (command_line.HasSwitch(switches::kProduction)) {\n+    is_production = true;\n+  }\n+  if (command_line.HasSwitch(switches::kDebug)) {\n+    is_debug = true;\n+  }\n+  if (command_line.HasSwitch(switches::kTesting)) {\n+    is_testing = true;\n+  }\n+\n+  bat_ads_service_->SetProduction(is_production, base::BindOnce(&Noop));\n+  bat_ads_service_->SetDebug(is_debug, base::BindOnce(&Noop));\n+  bat_ads_service_->SetTesting(is_testing, base::BindOnce(&Noop));\n+\n+  bat_ads_service_->Create(std::move(client_ptr_info), MakeRequest(&bat_ads_),\n+      base::BindOnce(&AdsServiceImpl::OnCreate, AsWeakPtr()));\n+}\n+\n+void AdsServiceImpl::Stop() {\n+  enabled_ = false;\n+  Shutdown();\n+}\n+\n+void AdsServiceImpl::ResetTimer() {\n+  idle_poll_timer_.Stop();\n+  idle_poll_timer_.Start(FROM_HERE,","path":"components/brave_ads/browser/ads_service_impl.cc","position":357,"original_position":355,"commit_id":"f49d972454a4d768343202605ead35bf0e55525f","original_commit_id":"32f9e20d8d751f9c73b45b037f6d05ddec825d33","user":{"login":"diracdeltas","id":549654,"node_id":"MDQ6VXNlcjU0OTY1NA==","avatar_url":"https://avatars1.githubusercontent.com/u/549654?v=4","gravatar_id":"","url":"https://api.github.com/users/diracdeltas","html_url":"https://github.com/diracdeltas","followers_url":"https://api.github.com/users/diracdeltas/followers","following_url":"https://api.github.com/users/diracdeltas/following{/other_user}","gists_url":"https://api.github.com/users/diracdeltas/gists{/gist_id}","starred_url":"https://api.github.com/users/diracdeltas/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/diracdeltas/subscriptions","organizations_url":"https://api.github.com/users/diracdeltas/orgs","repos_url":"https://api.github.com/users/diracdeltas/repos","events_url":"https://api.github.com/users/diracdeltas/events{/privacy}","received_events_url":"https://api.github.com/users/diracdeltas/received_events","type":"User","site_admin":false},"body":"@tmancey what is the range of x?","created_at":"2018-12-05T21:35:31Z","updated_at":"2018-12-05T21:35:31Z","html_url":"https://github.com/brave/brave-core/pull/765#discussion_r239246315","pull_request_url":"https://api.github.com/repos/brave/brave-core/pulls/765","author_association":"MEMBER","_links":{"self":{"href":"https://api.github.com/repos/brave/brave-core/pulls/comments/239246315"},"html":{"href":"https://github.com/brave/brave-core/pull/765#discussion_r239246315"},"pull_request":{"href":"https://api.github.com/repos/brave/brave-core/pulls/765"}},"in_reply_to_id":238805681},"pull_request":{"url":"https://api.github.com/repos/brave/brave-core/pulls/765","id":226776845,"node_id":"MDExOlB1bGxSZXF1ZXN0MjI2Nzc2ODQ1","html_url":"https://github.com/brave/brave-core/pull/765","diff_url":"https://github.com/brave/brave-core/pull/765.diff","patch_url":"https://github.com/brave/brave-core/pull/765.patch","issue_url":"https://api.github.com/repos/brave/brave-core/issues/765","number":765,"state":"open","locked":false,"title":"Brave ads","user":{"login":"bridiver","id":34129,"node_id":"MDQ6VXNlcjM0MTI5","avatar_url":"https://avatars3.githubusercontent.com/u/34129?v=4","gravatar_id":"","url":"https://api.github.com/users/bridiver","html_url":"https://github.com/bridiver","followers_url":"https://api.github.com/users/bridiver/followers","following_url":"https://api.github.com/users/bridiver/following{/other_user}","gists_url":"https://api.github.com/users/bridiver/gists{/gist_id}","starred_url":"https://api.github.com/users/bridiver/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/bridiver/subscriptions","organizations_url":"https://api.github.com/users/bridiver/orgs","repos_url":"https://api.github.com/users/bridiver/repos","events_url":"https://api.github.com/users/bridiver/events{/privacy}","received_events_url":"https://api.github.com/users/bridiver/received_events","type":"User","site_admin":false},"body":"## Submitter Checklist:\r\n\r\n- [ ] Submitted a [ticket](https://github.com/brave/brave-browser/issues) for my issue if one did not already exist.\r\n- [ ] Used Github [auto-closing keywords](https://help.github.com/articles/closing-issues-via-commit-messages/) in the commit message.\r\n- [ ] Added/updated tests for this change (for new code or code which already has tests).\r\n- Verified that these changes build without errors on\r\n  - [x] Windows\r\n  - [x] macOS\r\n  - [x] Linux\r\n- Verified that these changes pass automated tests (`npm test brave_unit_tests && npm test brave_browser_tests`) on\r\n  - [ ] Windows\r\n  - [ ] macOS\r\n  - [ ] Linux\r\n- [x] Ran `git rebase master` (if needed).\r\n- [x] Ran `git rebase -i` to squash commits (if needed).\r\n- [x] Tagged reviewers and labelled the pull request as needed.\r\n- [x] Request a security/privacy review as needed.\r\n- [ ] Add appropriate QA labels (QA/Yes or QA/No) to include the closed issue in milestone\r\n\r\n## Test Plan:\r\n\r\n\r\n## Reviewer Checklist:\r\n\r\n- [ ] New files have MPL-2.0 license header.\r\n- [ ] Request a security/privacy review as needed.\r\n- [ ] Adequate test coverage exists to prevent regressions \r\n- [ ] Verify test plan is specified in PR before merging to source","created_at":"2018-10-30T03:03:29Z","updated_at":"2018-12-05T21:35:31Z","closed_at":null,"merged_at":null,"merge_commit_sha":"8e69625580bc923912723b85ee11ac55814195b2","assignee":{"login":"bridiver","id":34129,"node_id":"MDQ6VXNlcjM0MTI5","avatar_url":"https://avatars3.githubusercontent.com/u/34129?v=4","gravatar_id":"","url":"https://api.github.com/users/bridiver","html_url":"https://github.com/bridiver","followers_url":"https://api.github.com/users/bridiver/followers","following_url":"https://api.github.com/users/bridiver/following{/other_user}","gists_url":"https://api.github.com/users/bridiver/gists{/gist_id}","starred_url":"https://api.github.com/users/bridiver/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/bridiver/subscriptions","organizations_url":"https://api.github.com/users/bridiver/orgs","repos_url":"https://api.github.com/users/bridiver/repos","events_url":"https://api.github.com/users/bridiver/events{/privacy}","received_events_url":"https://api.github.com/users/bridiver/received_events","type":"User","site_admin":false},"assignees":[{"login":"bridiver","id":34129,"node_id":"MDQ6VXNlcjM0MTI5","avatar_url":"https://avatars3.githubusercontent.com/u/34129?v=4","gravatar_id":"","url":"https://api.github.com/users/bridiver","html_url":"https://github.com/bridiver","followers_url":"https://api.github.com/users/bridiver/followers","following_url":"https://api.github.com/users/bridiver/following{/other_user}","gists_url":"https://api.github.com/users/bridiver/gists{/gist_id}","starred_url":"https://api.github.com/users/bridiver/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/bridiver/subscriptions","organizations_url":"https://api.github.com/users/bridiver/orgs","repos_url":"https://api.github.com/users/bridiver/repos","events_url":"https://api.github.com/users/bridiver/events{/privacy}","received_events_url":"https://api.github.com/users/bridiver/received_events","type":"User","site_admin":false}],"requested_reviewers":[{"login":"bbondy","id":831718,"node_id":"MDQ6VXNlcjgzMTcxOA==","avatar_url":"https://avatars2.githubusercontent.com/u/831718?v=4","gravatar_id":"","url":"https://api.github.com/users/bbondy","html_url":"https://github.com/bbondy","followers_url":"https://api.github.com/users/bbondy/followers","following_url":"https://api.github.com/users/bbondy/following{/other_user}","gists_url":"https://api.github.com/users/bbondy/gists{/gist_id}","starred_url":"https://api.github.com/users/bbondy/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/bbondy/subscriptions","organizations_url":"https://api.github.com/users/bbondy/orgs","repos_url":"https://api.github.com/users/bbondy/repos","events_url":"https://api.github.com/users/bbondy/events{/privacy}","received_events_url":"https://api.github.com/users/bbondy/received_events","type":"User","site_admin":false}],"requested_teams":[],"labels":[],"milestone":null,"commits_url":"https://api.github.com/repos/brave/brave-core/pulls/765/commits","review_comments_url":"https://api.github.com/repos/brave/brave-core/pulls/765/comments","review_comment_url":"https://api.github.com/repos/brave/brave-core/pulls/comments{/number}","comments_url":"https://api.github.com/repos/brave/brave-core/issues/765/comments","statuses_url":"https://api.github.com/repos/brave/brave-core/statuses/f49d972454a4d768343202605ead35bf0e55525f","head":{"label":"brave:brave-ads","ref":"brave-ads","sha":"f49d972454a4d768343202605ead35bf0e55525f","user":{"login":"brave","id":12301619,"node_id":"MDEyOk9yZ2FuaXphdGlvbjEyMzAxNjE5","avatar_url":"https://avatars1.githubusercontent.com/u/12301619?v=4","gravatar_id":"","url":"https://api.github.com/users/brave","html_url":"https://github.com/brave","followers_url":"https://api.github.com/users/brave/followers","following_url":"https://api.github.com/users/brave/following{/other_user}","gists_url":"https://api.github.com/users/brave/gists{/gist_id}","starred_url":"https://api.github.com/users/brave/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/brave/subscriptions","organizations_url":"https://api.github.com/users/brave/orgs","repos_url":"https://api.github.com/users/brave/repos","events_url":"https://api.github.com/users/brave/events{/privacy}","received_events_url":"https://api.github.com/users/brave/received_events","type":"Organization","site_admin":false},"repo":{"id":110198384,"node_id":"MDEwOlJlcG9zaXRvcnkxMTAxOTgzODQ=","name":"brave-core","full_name":"brave/brave-core","private":false,"owner":{"login":"brave","id":12301619,"node_id":"MDEyOk9yZ2FuaXphdGlvbjEyMzAxNjE5","avatar_url":"https://avatars1.githubusercontent.com/u/12301619?v=4","gravatar_id":"","url":"https://api.github.com/users/brave","html_url":"https://github.com/brave","followers_url":"https://api.github.com/users/brave/followers","following_url":"https://api.github.com/users/brave/following{/other_user}","gists_url":"https://api.github.com/users/brave/gists{/gist_id}","starred_url":"https://api.github.com/users/brave/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/brave/subscriptions","organizations_url":"https://api.github.com/users/brave/orgs","repos_url":"https://api.github.com/users/brave/repos","events_url":"https://api.github.com/users/brave/events{/privacy}","received_events_url":"https://api.github.com/users/brave/received_events","type":"Organization","site_admin":false},"html_url":"https://github.com/brave/brave-core","description":"Core engine for the Brave browser for macOS, Windows, Linux, and eventually Android. For the issue log, please see https://github.com/brave/brave-browser","fork":false,"url":"https://api.github.com/repos/brave/brave-core","forks_url":"https://api.github.com/repos/brave/brave-core/forks","keys_url":"https://api.github.com/repos/brave/brave-core/keys{/key_id}","collaborators_url":"https://api.github.com/repos/brave/brave-core/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/brave/brave-core/teams","hooks_url":"https://api.github.com/repos/brave/brave-core/hooks","issue_events_url":"https://api.github.com/repos/brave/brave-core/issues/events{/number}","events_url":"https://api.github.com/repos/brave/brave-core/events","assignees_url":"https://api.github.com/repos/brave/brave-core/assignees{/user}","branches_url":"https://api.github.com/repos/brave/brave-core/branches{/branch}","tags_url":"https://api.github.com/repos/brave/brave-core/tags","blobs_url":"https://api.github.com/repos/brave/brave-core/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/brave/brave-core/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/brave/brave-core/git/refs{/sha}","trees_url":"https://api.github.com/repos/brave/brave-core/git/trees{/sha}","statuses_url":"https://api.github.com/repos/brave/brave-core/statuses/{sha}","languages_url":"https://api.github.com/repos/brave/brave-core/languages","stargazers_url":"https://api.github.com/repos/brave/brave-core/stargazers","contributors_url":"https://api.github.com/repos/brave/brave-core/contributors","subscribers_url":"https://api.github.com/repos/brave/brave-core/subscribers","subscription_url":"https://api.github.com/repos/brave/brave-core/subscription","commits_url":"https://api.github.com/repos/brave/brave-core/commits{/sha}","git_commits_url":"https://api.github.com/repos/brave/brave-core/git/commits{/sha}","comments_url":"https://api.github.com/repos/brave/brave-core/comments{/number}","issue_comment_url":"https://api.github.com/repos/brave/brave-core/issues/comments{/number}","contents_url":"https://api.github.com/repos/brave/brave-core/contents/{+path}","compare_url":"https://api.github.com/repos/brave/brave-core/compare/{base}...{head}","merges_url":"https://api.github.com/repos/brave/brave-core/merges","archive_url":"https://api.github.com/repos/brave/brave-core/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/brave/brave-core/downloads","issues_url":"https://api.github.com/repos/brave/brave-core/issues{/number}","pulls_url":"https://api.github.com/repos/brave/brave-core/pulls{/number}","milestones_url":"https://api.github.com/repos/brave/brave-core/milestones{/number}","notifications_url":"https://api.github.com/repos/brave/brave-core/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/brave/brave-core/labels{/name}","releases_url":"https://api.github.com/repos/brave/brave-core/releases{/id}","deployments_url":"https://api.github.com/repos/brave/brave-core/deployments","created_at":"2017-11-10T03:33:30Z","updated_at":"2018-12-05T18:52:48Z","pushed_at":"2018-12-05T20:50:42Z","git_url":"git://github.com/brave/brave-core.git","ssh_url":"git@github.com:brave/brave-core.git","clone_url":"https://github.com/brave/brave-core.git","svn_url":"https://github.com/brave/brave-core","homepage":"","size":62097,"stargazers_count":218,"watchers_count":218,"language":"C++","has_issues":false,"has_projects":false,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":53,"mirror_url":null,"archived":false,"open_issues_count":34,"license":{"key":"other","name":"Other","spdx_id":"NOASSERTION","url":null,"node_id":"MDc6TGljZW5zZTA="},"forks":53,"open_issues":34,"watchers":218,"default_branch":"master"}},"base":{"label":"brave:master","ref":"master","sha":"c78d54221d4c4486db0b14aba9f1df189810213d","user":{"login":"brave","id":12301619,"node_id":"MDEyOk9yZ2FuaXphdGlvbjEyMzAxNjE5","avatar_url":"https://avatars1.githubusercontent.com/u/12301619?v=4","gravatar_id":"","url":"https://api.github.com/users/brave","html_url":"https://github.com/brave","followers_url":"https://api.github.com/users/brave/followers","following_url":"https://api.github.com/users/brave/following{/other_user}","gists_url":"https://api.github.com/users/brave/gists{/gist_id}","starred_url":"https://api.github.com/users/brave/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/brave/subscriptions","organizations_url":"https://api.github.com/users/brave/orgs","repos_url":"https://api.github.com/users/brave/repos","events_url":"https://api.github.com/users/brave/events{/privacy}","received_events_url":"https://api.github.com/users/brave/received_events","type":"Organization","site_admin":false},"repo":{"id":110198384,"node_id":"MDEwOlJlcG9zaXRvcnkxMTAxOTgzODQ=","name":"brave-core","full_name":"brave/brave-core","private":false,"owner":{"login":"brave","id":12301619,"node_id":"MDEyOk9yZ2FuaXphdGlvbjEyMzAxNjE5","avatar_url":"https://avatars1.githubusercontent.com/u/12301619?v=4","gravatar_id":"","url":"https://api.github.com/users/brave","html_url":"https://github.com/brave","followers_url":"https://api.github.com/users/brave/followers","following_url":"https://api.github.com/users/brave/following{/other_user}","gists_url":"https://api.github.com/users/brave/gists{/gist_id}","starred_url":"https://api.github.com/users/brave/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/brave/subscriptions","organizations_url":"https://api.github.com/users/brave/orgs","repos_url":"https://api.github.com/users/brave/repos","events_url":"https://api.github.com/users/brave/events{/privacy}","received_events_url":"https://api.github.com/users/brave/received_events","type":"Organization","site_admin":false},"html_url":"https://github.com/brave/brave-core","description":"Core engine for the Brave browser for macOS, Windows, Linux, and eventually Android. For the issue log, please see https://github.com/brave/brave-browser","fork":false,"url":"https://api.github.com/repos/brave/brave-core","forks_url":"https://api.github.com/repos/brave/brave-core/forks","keys_url":"https://api.github.com/repos/brave/brave-core/keys{/key_id}","collaborators_url":"https://api.github.com/repos/brave/brave-core/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/brave/brave-core/teams","hooks_url":"https://api.github.com/repos/brave/brave-core/hooks","issue_events_url":"https://api.github.com/repos/brave/brave-core/issues/events{/number}","events_url":"https://api.github.com/repos/brave/brave-core/events","assignees_url":"https://api.github.com/repos/brave/brave-core/assignees{/user}","branches_url":"https://api.github.com/repos/brave/brave-core/branches{/branch}","tags_url":"https://api.github.com/repos/brave/brave-core/tags","blobs_url":"https://api.github.com/repos/brave/brave-core/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/brave/brave-core/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/brave/brave-core/git/refs{/sha}","trees_url":"https://api.github.com/repos/brave/brave-core/git/trees{/sha}","statuses_url":"https://api.github.com/repos/brave/brave-core/statuses/{sha}","languages_url":"https://api.github.com/repos/brave/brave-core/languages","stargazers_url":"https://api.github.com/repos/brave/brave-core/stargazers","contributors_url":"https://api.github.com/repos/brave/brave-core/contributors","subscribers_url":"https://api.github.com/repos/brave/brave-core/subscribers","subscription_url":"https://api.github.com/repos/brave/brave-core/subscription","commits_url":"https://api.github.com/repos/brave/brave-core/commits{/sha}","git_commits_url":"https://api.github.com/repos/brave/brave-core/git/commits{/sha}","comments_url":"https://api.github.com/repos/brave/brave-core/comments{/number}","issue_comment_url":"https://api.github.com/repos/brave/brave-core/issues/comments{/number}","contents_url":"https://api.github.com/repos/brave/brave-core/contents/{+path}","compare_url":"https://api.github.com/repos/brave/brave-core/compare/{base}...{head}","merges_url":"https://api.github.com/repos/brave/brave-core/merges","archive_url":"https://api.github.com/repos/brave/brave-core/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/brave/brave-core/downloads","issues_url":"https://api.github.com/repos/brave/brave-core/issues{/number}","pulls_url":"https://api.github.com/repos/brave/brave-core/pulls{/number}","milestones_url":"https://api.github.com/repos/brave/brave-core/milestones{/number}","notifications_url":"https://api.github.com/repos/brave/brave-core/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/brave/brave-core/labels{/name}","releases_url":"https://api.github.com/repos/brave/brave-core/releases{/id}","deployments_url":"https://api.github.com/repos/brave/brave-core/deployments","created_at":"2017-11-10T03:33:30Z","updated_at":"2018-12-05T18:52:48Z","pushed_at":"2018-12-05T20:50:42Z","git_url":"git://github.com/brave/brave-core.git","ssh_url":"git@github.com:brave/brave-core.git","clone_url":"https://github.com/brave/brave-core.git","svn_url":"https://github.com/brave/brave-core","homepage":"","size":62097,"stargazers_count":218,"watchers_count":218,"language":"C++","has_issues":false,"has_projects":false,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":53,"mirror_url":null,"archived":false,"open_issues_count":34,"license":{"key":"other","name":"Other","spdx_id":"NOASSERTION","url":null,"node_id":"MDc6TGljZW5zZTA="},"forks":53,"open_issues":34,"watchers":218,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/brave/brave-core/pulls/765"},"html":{"href":"https://github.com/brave/brave-core/pull/765"},"issue":{"href":"https://api.github.com/repos/brave/brave-core/issues/765"},"comments":{"href":"https://api.github.com/repos/brave/brave-core/issues/765/comments"},"review_comments":{"href":"https://api.github.com/repos/brave/brave-core/pulls/765/comments"},"review_comment":{"href":"https://api.github.com/repos/brave/brave-core/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/brave/brave-core/pulls/765/commits"},"statuses":{"href":"https://api.github.com/repos/brave/brave-core/statuses/f49d972454a4d768343202605ead35bf0e55525f"}},"author_association":"COLLABORATOR"}}
{"actor":{"display_login":"diracdeltas"}}