Firefox-Marionette
view release on metacpan or search on metacpan
lib/Firefox/Marionette.pm view on Meta::CPAN
return bookmark;
})(arguments[0]);
return bookmarkStatus;
_JS_
$self->_context($old);
return $self;
}
sub delete_bookmark {
my ( $self, $bookmark ) = @_;
my $guid = $bookmark->guid();
my $old = $self->_context('chrome');
$self->script(
$self->_compress_script(
$self->_bookmark_interface_preamble()
. <<'_JS_' ), args => [$guid] );
return lazy.Bookmarks.remove(arguments[0]);
_JS_
$self->_context($old);
return $self;
}
sub _generate_history_guid {
my ($self) = @_;
# from GenerateGUID in ./toolkit/components/places/Helpers.cpp
my $guid = MIME::Base64::encode_base64(
Crypt::URandom::urandom( _SHORT_GUID_BYTES() ) );
$guid =~ s/\//-/smxg;
$guid =~ s/[+]/_/smxg;
chomp $guid;
return $guid;
}
sub import_bookmarks {
my ( $self, $path ) = @_;
my $read_handle = FileHandle->new( $path, Fcntl::O_RDONLY() )
or Firefox::Marionette::Exception->throw(
"Failed to open '$path' for reading:$EXTENDED_OS_ERROR");
binmode $read_handle;
my $contents;
my $result;
while ( $result =
$read_handle->read( my $buffer, _LOCAL_READ_BUFFER_SIZE() ) )
{
$contents .= $buffer;
}
my $default_menu_title = q[menu];
defined $result
or Firefox::Marionette::Exception->throw(
"Failed to read from '$path':$EXTENDED_OS_ERROR");
my $quoted_header_regex = quotemeta <<'_HTML_';
<!DOCTYPE NETSCAPE-Bookmark-file-1>
<!-- This is an automatically generated file.
It will be read and overwritten.
DO NOT EDIT! -->
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=UTF-8">
_HTML_
$quoted_header_regex =~ s/\\\r?\n/\\s+/smxg;
my $title_regex = qr/[<]TITLE[>]Bookmarks[<]\/TITLE[>]\s+/smx;
my $header_regex = qr/[<]H1[>]Bookmarks(?:[ ]Menu)?[<]\/H1[>]\s+/smx;
my $list_regex = qr/[<]DL[>][<]p[>]\s*/smx;
if ( $contents =~ s/\A\s*$quoted_header_regex\s*//smx ) {
$contents =~ s/\A\s*<meta[^>]+><\/meta>\s*//smx;
$contents =~ s/\A$title_regex$header_regex$list_regex//smx;
my %mapping = $self->_get_bookmark_mapping();
my $processing = 1;
my $index = 0;
my $json = {
title => q[],
index => $index++,
$mapping{type} => Firefox::Marionette::Bookmark::FOLDER(),
guid => Firefox::Marionette::Bookmark::ROOT(),
children => [],
};
my @folders;
push @folders, $json;
my $folder_name_regex = qr/(UNFILED_BOOKMARKS|PERSONAL_TOOLBAR)/smx;
my $folder_regex =
qr/\s*[<]DT[>]/smx
. qr/[<]H3(?:[ ]ADD_DATE="(\d+)")?(?:[ ]LAST_MODIFIED="(\d+)")?/smx
. qr/(?:[ ]${folder_name_regex}_FOLDER="true")?[>]/smx
. qr/([^<]+)\s*<\/H3>/smx;
my $bookmark_regex =
qr/\s*[<]DT[>][<]A[ ]HREF="([^"]+)"[ ]/smx
. qr/ADD_DATE="(\d+)"(?:[ ]LAST_MODIFIED="(\d+)")?/smx
. qr/(?:[ ]ICON_URI="([^"]+)")?(?:[ ]ICON="([^"]+)")?/smx
. qr/(?:[ ]SHORTCUTURL="([^"]+)")?(?:[ ]TAGS="([^"]+)")?[>]/smx
. qr/([^<]+)[<]\/A[>]\s*/smx;
while ($processing) {
$processing = 0;
if ( $contents =~ s/\A$folder_regex//smx ) {
my ( $add_date, $last_modified, $type_of_folder, $text ) =
( $1, $2, $3, $4 );
$processing = 1;
if ( !$type_of_folder ) {
my $implied_menu_folder = {
title =>
Encode::decode( 'UTF-8', $default_menu_title, 1 ),
index => $index++,
$mapping{type} =>
Firefox::Marionette::Bookmark::FOLDER(),
guid => Firefox::Marionette::Bookmark::MENU(),
children => [],
};
push @{ $folders[-1]->{children} }, $implied_menu_folder;
push @folders, $implied_menu_folder;
}
my $folder_name = $text;
my $folder = {
title => Encode::decode( 'UTF-8', $folder_name, 1 ),
index => $index++,
$mapping{type} => Firefox::Marionette::Bookmark::FOLDER(),
(
$type_of_folder
? (
$type_of_folder eq 'PERSONAL_TOOLBAR'
? ( guid =>
Firefox::Marionette::Bookmark::TOOLBAR() )
lib/Firefox/Marionette.pm view on Meta::CPAN
}
return $self->{_profile_directory};
}
sub _get_empty_port {
my ($self) = @_;
socket my $socket, Socket::PF_INET(), Socket::SOCK_STREAM(), 0
or Firefox::Marionette::Exception->throw(
"Failed to create a socket:$EXTENDED_OS_ERROR");
bind $socket, Socket::sockaddr_in( 0, Socket::INADDR_LOOPBACK() )
or Firefox::Marionette::Exception->throw(
"Failed to bind socket:$EXTENDED_OS_ERROR");
my $port = ( Socket::sockaddr_in( getsockname $socket ) )[0];
close $socket
or Firefox::Marionette::Exception->throw(
"Failed to close random socket:$EXTENDED_OS_ERROR");
return $port;
}
sub _get_local_port_for_profile_urls {
my ($self) = @_;
socket my $socket, Socket::PF_INET(), Socket::SOCK_STREAM(), 0
or Firefox::Marionette::Exception->throw(
"Failed to create a socket:$EXTENDED_OS_ERROR");
bind $socket, Socket::sockaddr_in( 0, Socket::INADDR_LOOPBACK() )
or Firefox::Marionette::Exception->throw(
"Failed to bind socket:$EXTENDED_OS_ERROR");
my $port = ( Socket::sockaddr_in( getsockname $socket ) )[0];
close $socket
or Firefox::Marionette::Exception->throw(
"Failed to close random socket:$EXTENDED_OS_ERROR");
return $port;
}
sub _setup_search_json_mozlz4 {
my ($self) = @_;
my $profile_directory = $self->{_profile_directory};
my $uncompressed = <<"_JSON_";
{"version":6,"engines":[{"_name":"DuckDuckGo","_isAppProvided":true,"_metaData":{}}],"metaData":{"useSavedOrder":false}}
_JSON_
chomp $uncompressed;
# my $content = _MAGIC_NUMBER_MOZL4Z() . Compress::LZ4::compress($uncompressed);
my $content = MIME::Base64::decode_base64(
'bW96THo0MAB4AAAA8Bd7InZlcnNpb24iOjYsImVuZ2luZXMiOlt7Il9uYW1lIjoiRHVjawQA9x1HbyIsIl9pc0FwcFByb3ZpZGVkIjp0cnVlLCJfbWV0YURhdGEiOnt9fV0sIhAA8AgidXNlU2F2ZWRPcmRlciI6ZmFsc2V9fQ=='
);
return $self->_copy_content_to_profile_directory( $content,
'search.json.mozlz4' );
}
sub _setup_empty_bookmarks {
my ($self) = @_;
my $now = time;
my $content = <<"_HTML_";
<!DOCTYPE NETSCAPE-Bookmark-file-1>
<!-- This is an automatically generated file.
It will be read and overwritten.
DO NOT EDIT! -->
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=UTF-8">
<TITLE>Bookmarks</TITLE>
<H1>Bookmarks Menu</H1>
<DL><p>
<DT><H3 ADD_DATE="$now" LAST_MODIFIED="$now" PERSONAL_TOOLBAR_FOLDER="true">Bookmarks Toolbar</H3>
<DL><p>
</DL><p>
<DT><H3 ADD_DATE="$now" LAST_MODIFIED="$now" UNFILED_BOOKMARKS_FOLDER="true">Other Bookmarks</H3>
<DL><p>
</DL><p>
</DL>
_HTML_
return $self->_copy_content_to_profile_directory( $content,
'bookmarks.html' );
}
sub _copy_content_to_profile_directory {
my ( $self, $content, $name ) = @_;
my $profile_directory = $self->{_profile_directory};
my $path;
if ( $self->_ssh() ) {
my $handle = File::Temp::tempfile(
File::Spec->catfile(
File::Spec->tmpdir(),
'firefox_marionette_local_bookmarks_XXXXXXXXXXX'
)
)
or Firefox::Marionette::Exception->throw(
"Failed to open temporary file for writing:$EXTENDED_OS_ERROR");
print {$handle} $content
or Firefox::Marionette::Exception->throw(
"Failed to write to temporary file:$EXTENDED_OS_ERROR");
seek $handle, 0, Fcntl::SEEK_SET()
or Firefox::Marionette::Exception->throw(
"Failed to seek to start of temporary file:$EXTENDED_OS_ERROR");
$path = $self->_remote_catfile( $profile_directory, $name );
$self->_put_file_via_scp( $handle, $path, $name );
if ( $self->_remote_uname() eq 'cygwin' ) {
$path = $self->_execute_via_ssh( {}, 'cygpath', '-l', '-w', $path );
chomp $path;
}
}
else {
$path = File::Spec->catfile( $profile_directory, $name );
my $handle =
FileHandle->new( $path,
Fcntl::O_CREAT() | Fcntl::O_EXCL() | Fcntl::O_WRONLY() )
or Firefox::Marionette::Exception->throw(
"Failed to open '$path' for writing:$EXTENDED_OS_ERROR");
print {$handle} $content
or Firefox::Marionette::Exception->throw(
"Failed to write to $path:$EXTENDED_OS_ERROR");
close $handle
or Firefox::Marionette::Exception->throw(
"Failed to close '$path':$EXTENDED_OS_ERROR");
if ( $OSNAME eq 'cygwin' ) {
$path = $self->execute( 'cygpath', '-s', '-w', $path );
chomp $path;
}
}
return $path;
}
( run in 1.947 second using v1.01-cache-2.11-cpan-cdf2f3d4e48 )