mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 19:57:35 +00:00
Browser+LibWeb+WebContent: Add ability to inspect local storage
The storage inspector now has a new tab for local storage. The next step would be to persist local storage and receive real-time notifications for changes to update the table view.
This commit is contained in:
parent
f2b4c044db
commit
45a81f5a2c
14 changed files with 168 additions and 4 deletions
|
@ -555,6 +555,10 @@ void BrowserWindow::create_new_tab(URL url, bool activate)
|
||||||
return m_cookie_jar.get_all_cookies();
|
return m_cookie_jar.get_all_cookies();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
new_tab.on_get_local_storage_entries = [this]() {
|
||||||
|
return active_tab().m_web_content_view->get_local_storage_entries();
|
||||||
|
};
|
||||||
|
|
||||||
new_tab.load(url);
|
new_tab.load(url);
|
||||||
|
|
||||||
dbgln_if(SPAM_DEBUG, "Added new tab {:p}, loading {}", &new_tab, url);
|
dbgln_if(SPAM_DEBUG, "Added new tab {:p}, loading {}", &new_tab, url);
|
||||||
|
|
|
@ -25,6 +25,7 @@ set(SOURCES
|
||||||
History.cpp
|
History.cpp
|
||||||
IconBag.cpp
|
IconBag.cpp
|
||||||
InspectorWidget.cpp
|
InspectorWidget.cpp
|
||||||
|
LocalStorageModel.cpp
|
||||||
StorageWidget.cpp
|
StorageWidget.cpp
|
||||||
StorageWidgetGML.h
|
StorageWidgetGML.h
|
||||||
Tab.cpp
|
Tab.cpp
|
||||||
|
|
69
Userland/Applications/Browser/LocalStorageModel.cpp
Normal file
69
Userland/Applications/Browser/LocalStorageModel.cpp
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2022, Valtteri Koskivuori <vkoskiv@gmail.com>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "LocalStorageModel.h"
|
||||||
|
|
||||||
|
namespace Browser {
|
||||||
|
|
||||||
|
void LocalStorageModel::set_items(OrderedHashMap<String, String> map)
|
||||||
|
{
|
||||||
|
begin_insert_rows({}, m_local_storage_entries.size(), m_local_storage_entries.size());
|
||||||
|
m_local_storage_entries = map;
|
||||||
|
end_insert_rows();
|
||||||
|
|
||||||
|
did_update(DontInvalidateIndices);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LocalStorageModel::clear_items()
|
||||||
|
{
|
||||||
|
begin_insert_rows({}, m_local_storage_entries.size(), m_local_storage_entries.size());
|
||||||
|
m_local_storage_entries.clear();
|
||||||
|
end_insert_rows();
|
||||||
|
|
||||||
|
did_update(DontInvalidateIndices);
|
||||||
|
}
|
||||||
|
|
||||||
|
String LocalStorageModel::column_name(int column) const
|
||||||
|
{
|
||||||
|
switch (column) {
|
||||||
|
case Column::Key:
|
||||||
|
return "Key";
|
||||||
|
case Column::Value:
|
||||||
|
return "Value";
|
||||||
|
case Column::__Count:
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
GUI::ModelIndex LocalStorageModel::index(int row, int column, GUI::ModelIndex const&) const
|
||||||
|
{
|
||||||
|
if (static_cast<size_t>(row) < m_local_storage_entries.size())
|
||||||
|
return create_index(row, column, NULL);
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
GUI::Variant LocalStorageModel::data(GUI::ModelIndex const& index, GUI::ModelRole role) const
|
||||||
|
{
|
||||||
|
if (role != GUI::ModelRole::Display)
|
||||||
|
return {};
|
||||||
|
|
||||||
|
auto const& keys = m_local_storage_entries.keys();
|
||||||
|
auto const& local_storage_key = keys[index.row()];
|
||||||
|
auto const& local_storage_value = m_local_storage_entries.get(local_storage_key).value_or({});
|
||||||
|
|
||||||
|
switch (index.column()) {
|
||||||
|
case Column::Key:
|
||||||
|
return local_storage_key;
|
||||||
|
case Column::Value:
|
||||||
|
return local_storage_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
VERIFY_NOT_REACHED();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
33
Userland/Applications/Browser/LocalStorageModel.h
Normal file
33
Userland/Applications/Browser/LocalStorageModel.h
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2022, Valtteri Koskivuori <vkoskiv@gmail.com>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <LibGUI/Model.h>
|
||||||
|
|
||||||
|
namespace Browser {
|
||||||
|
|
||||||
|
class LocalStorageModel final : public GUI::Model {
|
||||||
|
public:
|
||||||
|
enum Column {
|
||||||
|
Key,
|
||||||
|
Value,
|
||||||
|
__Count,
|
||||||
|
};
|
||||||
|
|
||||||
|
void set_items(OrderedHashMap<String, String> map);
|
||||||
|
void clear_items();
|
||||||
|
virtual int row_count(GUI::ModelIndex const&) const override { return m_local_storage_entries.size(); }
|
||||||
|
virtual int column_count(GUI::ModelIndex const& = GUI::ModelIndex()) const override { return Column::__Count; }
|
||||||
|
virtual String column_name(int column) const override;
|
||||||
|
virtual GUI::ModelIndex index(int row, int column = 0, GUI::ModelIndex const& = GUI::ModelIndex()) const override;
|
||||||
|
virtual GUI::Variant data(GUI::ModelIndex const& index, GUI::ModelRole role = GUI::ModelRole::Display) const override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
OrderedHashMap<String, String> m_local_storage_entries;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
#include "StorageWidget.h"
|
#include "StorageWidget.h"
|
||||||
#include "CookiesModel.h"
|
#include "CookiesModel.h"
|
||||||
|
#include "LocalStorageModel.h"
|
||||||
#include <AK/Variant.h>
|
#include <AK/Variant.h>
|
||||||
#include <Applications/Browser/CookiesTabGML.h>
|
#include <Applications/Browser/CookiesTabGML.h>
|
||||||
#include <Applications/Browser/StorageWidgetGML.h>
|
#include <Applications/Browser/StorageWidgetGML.h>
|
||||||
|
@ -26,12 +27,25 @@ StorageWidget::StorageWidget()
|
||||||
m_cookies_table_view = cookies_tab->find_descendant_of_type_named<GUI::TableView>("cookies_tableview");
|
m_cookies_table_view = cookies_tab->find_descendant_of_type_named<GUI::TableView>("cookies_tableview");
|
||||||
m_cookies_model = adopt_ref(*new CookiesModel());
|
m_cookies_model = adopt_ref(*new CookiesModel());
|
||||||
|
|
||||||
m_sorting_model = MUST(GUI::SortingProxyModel::create(*m_cookies_model));
|
m_cookie_sorting_model = MUST(GUI::SortingProxyModel::create(*m_cookies_model));
|
||||||
m_sorting_model->set_sort_role(GUI::ModelRole::Display);
|
m_cookie_sorting_model->set_sort_role(GUI::ModelRole::Display);
|
||||||
|
|
||||||
m_cookies_table_view->set_model(m_sorting_model);
|
m_cookies_table_view->set_model(m_cookie_sorting_model);
|
||||||
m_cookies_table_view->set_column_headers_visible(true);
|
m_cookies_table_view->set_column_headers_visible(true);
|
||||||
m_cookies_table_view->set_alternating_row_colors(true);
|
m_cookies_table_view->set_alternating_row_colors(true);
|
||||||
|
|
||||||
|
auto local_storage_tab = tab_widget.try_add_tab<GUI::Widget>("Local Storage").release_value_but_fixme_should_propagate_errors();
|
||||||
|
local_storage_tab->load_from_gml(cookies_tab_gml);
|
||||||
|
|
||||||
|
m_local_storage_table_view = local_storage_tab->find_descendant_of_type_named<GUI::TableView>("cookies_tableview");
|
||||||
|
m_local_storage_model = adopt_ref(*new LocalStorageModel());
|
||||||
|
|
||||||
|
m_local_storage_sorting_model = MUST(GUI::SortingProxyModel::create(*m_local_storage_model));
|
||||||
|
m_local_storage_sorting_model->set_sort_role(GUI::ModelRole::Display);
|
||||||
|
|
||||||
|
m_local_storage_table_view->set_model(m_local_storage_sorting_model);
|
||||||
|
m_local_storage_table_view->set_column_headers_visible(true);
|
||||||
|
m_local_storage_table_view->set_alternating_row_colors(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void StorageWidget::add_cookie(Web::Cookie::Cookie const& cookie)
|
void StorageWidget::add_cookie(Web::Cookie::Cookie const& cookie)
|
||||||
|
@ -44,4 +58,14 @@ void StorageWidget::clear_cookies()
|
||||||
m_cookies_model->clear_items();
|
m_cookies_model->clear_items();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void StorageWidget::set_local_storage_entries(OrderedHashMap<String, String> entries)
|
||||||
|
{
|
||||||
|
m_local_storage_model->set_items(entries);
|
||||||
|
}
|
||||||
|
|
||||||
|
void StorageWidget::clear_local_storage_entries()
|
||||||
|
{
|
||||||
|
m_local_storage_model->clear_items();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "CookiesModel.h"
|
#include "CookiesModel.h"
|
||||||
|
#include "LocalStorageModel.h"
|
||||||
#include "Tab.h"
|
#include "Tab.h"
|
||||||
#include <LibGUI/SortingProxyModel.h>
|
#include <LibGUI/SortingProxyModel.h>
|
||||||
#include <LibGUI/Widget.h>
|
#include <LibGUI/Widget.h>
|
||||||
|
@ -22,12 +23,18 @@ public:
|
||||||
void add_cookie(Web::Cookie::Cookie const& cookie);
|
void add_cookie(Web::Cookie::Cookie const& cookie);
|
||||||
void clear_cookies();
|
void clear_cookies();
|
||||||
|
|
||||||
|
void set_local_storage_entries(OrderedHashMap<String, String> entries);
|
||||||
|
void clear_local_storage_entries();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
StorageWidget();
|
StorageWidget();
|
||||||
|
|
||||||
RefPtr<GUI::TableView> m_cookies_table_view;
|
RefPtr<GUI::TableView> m_cookies_table_view;
|
||||||
RefPtr<CookiesModel> m_cookies_model;
|
RefPtr<CookiesModel> m_cookies_model;
|
||||||
RefPtr<GUI::SortingProxyModel> m_sorting_model;
|
RefPtr<GUI::SortingProxyModel> m_cookie_sorting_model;
|
||||||
|
RefPtr<GUI::TableView> m_local_storage_table_view;
|
||||||
|
RefPtr<LocalStorageModel> m_local_storage_model;
|
||||||
|
RefPtr<GUI::SortingProxyModel> m_local_storage_sorting_model;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -613,6 +613,12 @@ void Tab::show_storage_inspector()
|
||||||
m_storage_widget->add_cookie(cookie);
|
m_storage_widget->add_cookie(cookie);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (on_get_local_storage_entries) {
|
||||||
|
auto local_storage_entries = on_get_local_storage_entries();
|
||||||
|
m_storage_widget->clear_local_storage_entries();
|
||||||
|
m_storage_widget->set_local_storage_entries(local_storage_entries);
|
||||||
|
}
|
||||||
|
|
||||||
auto* window = m_storage_widget->window();
|
auto* window = m_storage_widget->window();
|
||||||
window->show();
|
window->show();
|
||||||
window->move_to_front();
|
window->move_to_front();
|
||||||
|
|
|
@ -65,6 +65,7 @@ public:
|
||||||
Function<void(const URL&, Web::Cookie::ParsedCookie const& cookie, Web::Cookie::Source source)> on_set_cookie;
|
Function<void(const URL&, Web::Cookie::ParsedCookie const& cookie, Web::Cookie::Source source)> on_set_cookie;
|
||||||
Function<void()> on_dump_cookies;
|
Function<void()> on_dump_cookies;
|
||||||
Function<Vector<Web::Cookie::Cookie>()> on_want_cookies;
|
Function<Vector<Web::Cookie::Cookie>()> on_want_cookies;
|
||||||
|
Function<OrderedHashMap<String, String>()> on_get_local_storage_entries;
|
||||||
|
|
||||||
enum class InspectorTarget {
|
enum class InspectorTarget {
|
||||||
Document,
|
Document,
|
||||||
|
|
|
@ -32,6 +32,8 @@ public:
|
||||||
|
|
||||||
Vector<String> supported_property_names() const;
|
Vector<String> supported_property_names() const;
|
||||||
|
|
||||||
|
auto const& map() const { return m_map; }
|
||||||
|
|
||||||
void dump() const;
|
void dump() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -490,6 +490,11 @@ String OutOfProcessWebView::dump_layout_tree()
|
||||||
return client().dump_layout_tree();
|
return client().dump_layout_tree();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
OrderedHashMap<String, String> OutOfProcessWebView::get_local_storage_entries()
|
||||||
|
{
|
||||||
|
return client().get_local_storage_entries();
|
||||||
|
}
|
||||||
|
|
||||||
void OutOfProcessWebView::set_content_filters(Vector<String> filters)
|
void OutOfProcessWebView::set_content_filters(Vector<String> filters)
|
||||||
{
|
{
|
||||||
client().async_set_content_filters(filters);
|
client().async_set_content_filters(filters);
|
||||||
|
|
|
@ -55,6 +55,8 @@ public:
|
||||||
|
|
||||||
String dump_layout_tree();
|
String dump_layout_tree();
|
||||||
|
|
||||||
|
OrderedHashMap<String, String> get_local_storage_entries();
|
||||||
|
|
||||||
void set_content_filters(Vector<String>);
|
void set_content_filters(Vector<String>);
|
||||||
void set_preferred_color_scheme(Web::CSS::PreferredColorScheme);
|
void set_preferred_color_scheme(Web::CSS::PreferredColorScheme);
|
||||||
|
|
||||||
|
|
|
@ -468,4 +468,10 @@ void ConnectionFromClient::set_is_scripting_enabled(bool is_scripting_enabled)
|
||||||
m_page_host->set_is_scripting_enabled(is_scripting_enabled);
|
m_page_host->set_is_scripting_enabled(is_scripting_enabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Messages::WebContentServer::GetLocalStorageEntriesResponse ConnectionFromClient::get_local_storage_entries()
|
||||||
|
{
|
||||||
|
auto* document = page().top_level_browsing_context().active_document();
|
||||||
|
auto local_storage = document->window().local_storage();
|
||||||
|
return local_storage->map();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -67,6 +67,8 @@ private:
|
||||||
virtual void run_javascript(String const&) override;
|
virtual void run_javascript(String const&) override;
|
||||||
virtual void js_console_request_messages(i32) override;
|
virtual void js_console_request_messages(i32) override;
|
||||||
|
|
||||||
|
virtual Messages::WebContentServer::GetLocalStorageEntriesResponse get_local_storage_entries() override;
|
||||||
|
|
||||||
virtual Messages::WebContentServer::GetSelectedTextResponse get_selected_text() override;
|
virtual Messages::WebContentServer::GetSelectedTextResponse get_selected_text() override;
|
||||||
virtual void select_all() override;
|
virtual void select_all() override;
|
||||||
|
|
||||||
|
|
|
@ -47,4 +47,6 @@ endpoint WebContentServer
|
||||||
set_has_focus(bool has_focus) =|
|
set_has_focus(bool has_focus) =|
|
||||||
set_is_scripting_enabled(bool is_scripting_enabled) =|
|
set_is_scripting_enabled(bool is_scripting_enabled) =|
|
||||||
|
|
||||||
|
get_local_storage_entries() => (OrderedHashMap<String,String> entries)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue