#include <litehtml/url_path.h>
#include <litehtml/url.h>
#include "web_page.h"
void litebrowser::text_file::on_data(void* data, size_t len, size_t , size_t )
{
stream.write((const char*) data, (std::streamsize) len);
}
void litebrowser::text_file::on_page_downloaded(u_int32_t http_status,
u_int32_t err_code,
const std::string &)
{
if(err_code == 0 && (http_status == 200 || http_status == 0))
{
data_ready = true;
} else
{
data_ready = false;
}
wait_mutex.unlock();
}
void litebrowser::web_page::open(const std::string &url, const std::string &fragment)
{
litehtml::url l_url(url);
if(!l_url.has_scheme())
{
if(url.front() != '/')
{
m_url = "http://" + url;
} else
{
m_url = url;
}
} else
{
m_url = url;
}
m_base_url = m_url;
m_fragment = fragment;
auto data = std::make_shared<text_file>();
auto cb_on_data = [data](void* in_data, size_t len, size_t , size_t ) { data->on_data(in_data, len, 0, 0); };
auto shared_this = shared_from_this();
auto cb_on_finish = [shared_this, data](u_int32_t http_status, u_int32_t err_code, const std::string &err_text, const std::string& url)
{
shared_this->on_page_downloaded(data, http_status, err_code, err_text, url);
};
http_request(m_url, cb_on_data, cb_on_finish);
}
void litebrowser::web_page::get_viewport(litehtml::position& viewport) const
{
m_html_host->get_viewport(viewport);
}
void litebrowser::web_page::on_anchor_click(const char* url, const litehtml::element::ptr& )
{
if(url)
{
make_url(url, m_base_url.c_str(), m_clicked_url);
}
}
void litebrowser::web_page::set_cursor(const char* cursor)
{
if(cursor)
{
if(m_cursor != cursor)
{
m_cursor = cursor;
m_html_host->update_cursor();
}
}
}
void litebrowser::web_page::import_css(litehtml::string& text, const litehtml::string& url, litehtml::string& baseurl)
{
std::string css_url;
make_url(url.c_str(), baseurl.c_str(), css_url);
auto data = std::make_shared<text_file>();
auto cb_on_data = [data](void* in_data, size_t len, size_t , size_t ) { data->on_data(in_data, len, 0, 0); };
auto cb_on_finish = [data](u_int32_t http_status, u_int32_t err_code, const std::string &err_text, const std::string& )
{
data->on_page_downloaded(http_status, err_code, err_text);
};
http_request(css_url, cb_on_data, cb_on_finish);
data->wait();
text = data->str();
if(!text.empty())
{
baseurl = css_url;
}
}
void litebrowser::web_page::set_caption(const char* caption)
{
m_notify->on_set_caption(caption);
}
void litebrowser::web_page::set_base_url(const char* base_url)
{
if(base_url)
{
m_base_url = litehtml::resolve(litehtml::url(m_url), litehtml::url(base_url)).str();
} else
{
m_base_url = m_url;
}
}
cairo_surface_t* litebrowser::web_page::get_image(const std::string& url)
{
return m_images.get_image(url);
}
void litebrowser::web_page::show_fragment(const litehtml::string& fragment)
{
std::lock_guard<std::recursive_mutex> html_lock(m_html_mutex);
if(fragment.empty() || !m_html)
{
m_html_host->scroll_to(0, 0);
} else
{
auto escaped_hash = litehtml::get_escaped_string(fragment);
std::string selector = ":is([id=\"" + escaped_hash + "\"],[name=\"" + escaped_hash + "\"])";
litehtml::element::ptr el = m_html->root()->select_one(selector);
if (el)
{
litehtml::position pos = el->get_placement();
m_html_host->scroll_to(0, pos.top());
}
}
}
void litebrowser::web_page::make_url(const char* url, const char* basepath, litehtml::string& out)
{
if(!basepath || !basepath[0])
{
if(!m_base_url.empty())
{
out = litehtml::resolve(litehtml::url(m_base_url), litehtml::url(url)).str();
} else
{
out = url;
}
} else
{
out = litehtml::resolve(litehtml::url(basepath), litehtml::url(url)).str();
}
}
void litebrowser::web_page::on_mouse_over(int x, int y, int client_x, int client_y)
{
std::lock_guard<std::recursive_mutex> html_lock(m_html_mutex);
if(m_html)
{
litehtml::position::vector redraw_boxes;
if(m_html->on_mouse_over(x, y, client_x, client_y, redraw_boxes))
{
m_html_host->redraw_boxes(redraw_boxes);
}
}
}
void litebrowser::web_page::on_lbutton_down(int x, int y, int client_x, int client_y)
{
std::lock_guard<std::recursive_mutex> html_lock(m_html_mutex);
if(m_html)
{
litehtml::position::vector redraw_boxes;
if(m_html->on_lbutton_down(x, y, client_x, client_y, redraw_boxes))
{
m_html_host->redraw_boxes(redraw_boxes);
}
}
}
void litebrowser::web_page::on_lbutton_up(int x, int y, int client_x, int client_y)
{
if(m_html)
{
{
std::lock_guard<std::recursive_mutex> html_lock(m_html_mutex);
litehtml::position::vector redraw_boxes;
m_clicked_url.clear();
if (m_html->on_lbutton_up(x, y, client_x, client_y, redraw_boxes))
{
m_html_host->redraw_boxes(redraw_boxes);
}
}
if(!m_clicked_url.empty())
{
m_html_host->open_url(m_clicked_url);
}
}
}
void litebrowser::web_page::on_page_downloaded(std::shared_ptr<text_file> data,
u_int32_t ,
u_int32_t err_code,
const std::string &err_text, const std::string& url)
{
if(err_code == 0)
{
m_url = url;
std::lock_guard<std::recursive_mutex> html_lock(m_html_mutex);
data->set_ready();
m_html_source = data->str();
} else
{
std::lock_guard<std::recursive_mutex> html_lock(m_html_mutex);
std::stringstream ss;
ss << "<h1>Impossible to load page</h1>" << std::endl;
ss << "<p>Error #" << err_code << ": " << err_text << "</p>" << std::endl;
m_html_source = ss.str();
}
m_html = litehtml::document::createFromString(m_html_source, this);
if (m_html)
{
std::lock_guard<std::recursive_mutex> html_lock(m_html_mutex);
int render_width = m_html_host->get_render_width();
m_html->render(render_width);
}
m_notify->on_page_loaded(id());
}
void litebrowser::web_page::on_image_downloaded(std::shared_ptr<image_file> data,
u_int32_t http_status,
u_int32_t err_code,
const std::string &,
const std::string& )
{
data->close();
if(!data->path().empty() && !err_code && (http_status == 200 || http_status == 0))
{
auto ptr = m_html_host->load_image(data->path());
if(ptr)
{
m_images.add_image(data->url(), ptr);
if(data->redraw_only())
{
m_notify->redraw();
} else
{
m_notify->render();
}
}
}
unlink(data->path().c_str());
}
void litebrowser::web_page::load_image(const char *src, const char *baseurl, bool redraw_on_ready)
{
std::string url;
make_url(src, baseurl, url);
if(m_images.reserve(url))
{
auto data = std::make_shared<image_file>(url, redraw_on_ready);
auto cb_on_data = [data](void* in_data, size_t len, size_t , size_t ) { data->on_data(in_data, len, 0, 0); };
auto shared_this = shared_from_this();
auto cb_on_finish = [shared_this, data](u_int32_t http_status, u_int32_t err_code, const std::string &err_text, const std::string& url)
{
shared_this->on_image_downloaded(data, http_status, err_code, err_text, url);
};
http_request(url, cb_on_data, cb_on_finish);
}
}
void litebrowser::web_page::http_request(const std::string &url,
const std::function<void(void *, size_t, size_t, size_t)> &cb_on_data,
const std::function<void(u_int32_t, u_int32_t, const std::string &, const std::string &)> &cb_on_finish)
{
m_requests_pool.enqueue(url, cb_on_data, cb_on_finish);
}
void litebrowser::web_page::on_pool_update_state()
{
m_notify->update_state();
}
double litebrowser::web_page::get_screen_dpi() const
{
return m_html_host->get_dpi();
}
int litebrowser::web_page::get_screen_width() const
{
return m_html_host->get_screen_width();
}
int litebrowser::web_page::get_screen_height() const
{
return m_html_host->get_screen_height();
}
void litebrowser::web_page::on_mouse_event(const litehtml::element::ptr& , litehtml::mouse_event )
{
}
litebrowser::image_file::image_file(std::string url, bool redraw_on_ready) :
m_url(std::move(url)),
m_redraw_on_ready(redraw_on_ready)
{
}
void litebrowser::image_file::on_data(void *data, size_t len, size_t , size_t )
{
if(m_fd < 0)
{
char nameBuff[] = "/tmp/litebrowser-XXXXXX";
m_fd = mkstemp(nameBuff);
if(m_fd >= 0)
{
m_path = nameBuff;
}
}
if(m_fd >= 0)
{
write(m_fd, data, len);
}
}