ContentFilterSettingsWidget.cpp 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. /*
  2. * Copyright (c) 2022, Maciej Zygmanowski <sppmacd@pm.me>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include "ContentFilterSettingsWidget.h"
  7. #include <AK/NonnullRefPtr.h>
  8. #include <Applications/BrowserSettings/ContentFilterSettingsWidgetGML.h>
  9. #include <LibConfig/Client.h>
  10. #include <LibCore/StandardPaths.h>
  11. #include <LibCore/Stream.h>
  12. #include <LibGUI/CheckBox.h>
  13. #include <LibGUI/Event.h>
  14. #include <LibGUI/Forward.h>
  15. #include <LibGUI/InputBox.h>
  16. #include <LibGUI/ListView.h>
  17. #include <LibGUI/Menu.h>
  18. static bool default_enable_content_filtering = true;
  19. static String filter_list_file_path()
  20. {
  21. return String::formatted("{}/BrowserContentFilters.txt", Core::StandardPaths::config_directory());
  22. }
  23. ErrorOr<void> DomainListModel::load()
  24. {
  25. // FIXME: This should be somewhat shared with Browser.
  26. auto file = TRY(Core::Stream::File::open(filter_list_file_path(), Core::Stream::OpenMode::Read));
  27. auto content_filter_list = TRY(Core::Stream::BufferedFile::create(move(file)));
  28. auto buffer = TRY(ByteBuffer::create_uninitialized(4096));
  29. while (TRY(content_filter_list->can_read_line())) {
  30. auto line = TRY(content_filter_list->read_line(buffer));
  31. dbgln("Content filter for {}", line);
  32. if (!line.is_empty())
  33. m_domain_list.append(line);
  34. }
  35. return {};
  36. }
  37. ErrorOr<void> DomainListModel::save()
  38. {
  39. if (!m_was_modified)
  40. return {};
  41. m_was_modified = false;
  42. StringBuilder builder;
  43. for (auto const& domain : m_domain_list)
  44. TRY(builder.try_appendff("{}\n", domain));
  45. auto file = TRY(Core::Stream::File::open(filter_list_file_path(), Core::Stream::OpenMode::Write));
  46. TRY(file->write(builder.to_byte_buffer().bytes()));
  47. return {};
  48. }
  49. void DomainListModel::add_domain(String name)
  50. {
  51. begin_insert_rows({}, m_domain_list.size(), m_domain_list.size());
  52. m_domain_list.append(move(name));
  53. end_insert_rows();
  54. m_was_modified = true;
  55. did_update(UpdateFlag::DontInvalidateIndices);
  56. }
  57. void DomainListModel::delete_domain(size_t index)
  58. {
  59. begin_delete_rows({}, index, index);
  60. m_domain_list.remove(index);
  61. end_delete_rows();
  62. m_was_modified = true;
  63. did_update(UpdateFlag::DontInvalidateIndices);
  64. }
  65. void DomainListModel::reset_default_values()
  66. {
  67. // FIXME: This probably should not be hardcoded.
  68. m_domain_list = {
  69. "207.net",
  70. "247realmedia.com",
  71. "2o7.net",
  72. "adbrite.com",
  73. "admob.com",
  74. "adthis.com",
  75. "advertising.com",
  76. "aquantive.com",
  77. "atwola.com",
  78. "channelintelligence.com",
  79. "doubleclick.com",
  80. "doubleclick.net",
  81. "esomniture.com",
  82. "google-analytics.com",
  83. "googleadservices.com",
  84. "googlesyndication.com",
  85. "gravity.com",
  86. "hitbox.com",
  87. "intellitxt.com",
  88. "nielsen-online.com",
  89. "omniture.com",
  90. "quantcast.com",
  91. "quantserve.com",
  92. "scorecardresearch.com",
  93. };
  94. m_was_modified = true;
  95. did_update(UpdateFlag::InvalidateAllIndices);
  96. }
  97. ContentFilterSettingsWidget::ContentFilterSettingsWidget()
  98. {
  99. load_from_gml(content_filter_settings_widget_gml);
  100. m_enable_content_filtering_checkbox = find_descendant_of_type_named<GUI::CheckBox>("enable_content_filtering_checkbox");
  101. m_domain_list_view = find_descendant_of_type_named<GUI::ListView>("domain_list_view");
  102. m_add_new_domain_button = find_descendant_of_type_named<GUI::Button>("add_new_domain_button");
  103. m_enable_content_filtering_checkbox->set_checked(Config::read_bool("Browser", "Preferences", "EnableContentFilters"), GUI::AllowCallback::No);
  104. m_enable_content_filtering_checkbox->on_checked = [&](auto) { set_modified(true); };
  105. m_add_new_domain_button->on_click = [&](unsigned) {
  106. String text;
  107. if (GUI::InputBox::show(window(), text, "Enter domain name", "Add domain to Content Filter") == GUI::Dialog::ExecResult::OK) {
  108. m_domain_list_model->add_domain(std::move(text));
  109. set_modified(true);
  110. }
  111. };
  112. m_domain_list_model = make_ref_counted<DomainListModel>();
  113. // FIXME: Propagate errors
  114. MUST(m_domain_list_model->load());
  115. m_domain_list_view->set_model(m_domain_list_model);
  116. auto delete_action = GUI::CommonActions::make_delete_action([&](GUI::Action const&) {
  117. if (!m_domain_list_view->selection().is_empty()) {
  118. m_domain_list_model->delete_domain(m_domain_list_view->selection().first().row());
  119. set_modified(true);
  120. }
  121. });
  122. m_entry_context_menu = GUI::Menu::construct();
  123. m_entry_context_menu->add_action(delete_action);
  124. m_domain_list_view->on_context_menu_request = [&](GUI::ModelIndex const& index, GUI::ContextMenuEvent const& event) {
  125. m_domain_list_view->set_cursor(index, GUI::AbstractView::SelectionUpdate::Set);
  126. m_entry_context_menu->popup(event.screen_position());
  127. };
  128. }
  129. void ContentFilterSettingsWidget::apply_settings()
  130. {
  131. // FIXME: Propagate errors
  132. MUST(m_domain_list_model->save());
  133. Config::write_bool("Browser", "Preferences", "EnableContentFilters", m_enable_content_filtering_checkbox->is_checked());
  134. }
  135. void ContentFilterSettingsWidget::reset_default_values()
  136. {
  137. m_domain_list_model->reset_default_values();
  138. m_enable_content_filtering_checkbox->set_checked(default_enable_content_filtering);
  139. }