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 )