Pinterest 扩展如何存储(临时)网页中的图像,然后在 iframe 中访问它们

How Pinterest extension store (temporarily) images from a web page and then access them in an iframe?

本文关键字:然后 iframe 访问 图像 网页 何存储 扩展 存储 Pinterest 临时      更新时间:2023-09-26

我一直在尝试创建一个像chrome扩展一样的Pin It按钮(Pinterest的扩展(。

我尝试的是单击扩展名时触发一个脚本,该脚本可以循环访问网页上的所有可用图像并将其存储在localStorage中。现在我需要调用 iframe(当然是不同的域(访问这些图像。由于只能从同一域访问本地存储,因此我很困惑Pinterest如何设法存储网页中的所有图像(临时而不是在其服务器上(,然后在iframe中使用它。

我还看到了 PinIt 按钮扩展的代码,但我无法从中理解任何东西,因为它被混淆/加密或其他什么。

我已经阅读了有关chrome.storage api 的信息,但我无法很好地理解它。我什至不确定在这种情况下这是否是我需要做的事情。(这是我第一次开发chrome扩展程序(。任何人都可以对此有所了解并指导我实现此功能的最佳方法吗?

附言我已经在不使用<iframe>的情况下完成了这个扩展,但是我需要用<iframe>来完成。

编辑 1:我不能在这里编写完整的代码,但这里是流程/结构/我的尝试
我从background.js
开始

chrome.browserAction.onClicked.addListener(function (tab) { /*This fxn fires when extension is clicked*/
    chrome.tabs.executeScript(tab.id, {
        "file": "bookmarklet.js"/*Calls this file*/
    })
});


bookmarklet.js

jQuery('body').append('<iframe class="vw_parent" id="image-grabber-container" src="" style="height: 100% !important;    width: 100% !important; position: fixed !important; margin: 0% auto !important; background: rgba(17, 17, 17, 0.9) !important; left: 0 !important; right: 0 !important; z-index: 999999999 !important; top: 0% !important;"></iframe>');
jQuery('img').each(function() {
   //do some checks to determine what images need to be stored
   var allImgs = jQuery(this); 
   localStorage.setItem('myLocalImgs', allImgs);
})
vwgrid = "https://mydomain/FileToBeInjectedInIframe.php";
jQuery('#image-grabber-container').attr('src', vwgrid);


现在在FileToBeInjectedInIframe.php

var abcde = localStorage.getItem('myLocalImgs');
console.log(abcde);
//This gives NULL value



编辑2: 根据 DelightedD0D 的评论和回答,我想解释一下这个扩展如何工作/应该工作
1.用户在任何网页上,然后单击扩展程序
2.该网页上的所有可用图像都显示在iFrame
中3.用户可以从此iFrame中选择多个图像,然后将它们发布到我的网站
4. iFrame的原因:如果用户点击iFrame中可用的"发布图像"按钮,并且他没有登录我们的网站发布图像,他应该在同一iFrame
中看到一个登录弹出窗口5. 如果不是iFrame,我将如何检查用户是否登录了我的网站,因为我将无法读取不同域上不同域的会话/cookie。

出于同样的原因,我相信(我不确定(,pinterest也在iFrame中显示图像。

TL;DR,链接到底部的示例扩展;)

好的,你的问题有点宽泛,但我会尝试解释如果我想这样做我会采取的方法。

首先,我会放弃iFrame。我看不出有任何理由在这里使用一个,我只是个人不喜欢它们。

我会:

  • 有一个注入到所有页面的内容脚本(如果需要,也可以输入特定的页面,等等(
  • 脚本将具有一个 JavaScript 类,该类将chrome.runtime.onMessage.addListener添加到页面
  • 此类将侦听来自扩展的消息
  • 消息将发送到此类以触发函数并发回响应
  • 例如,像 {pageAction:"getImages"} 这样的消息将触发注入类中的 getImages 函数
  • getImages将获取所有图像并将它们发送回扩展程序

这里有一点需要注意的是,我更喜欢使用编码为 base64 字符串的图像,而不是来自一大堆不同域和所有 CORR、链接保护的图像 url,....等。出于这个原因,我会让getImages进行 ajax 调用来encodeImagesToBase64.php传递图像 url 数组的服务器。 encodeImagesToBase64.php将返回一个 base64 图像数组,然后将其发送到扩展。

  • 现在,扩展具有 base64 图像数组,Id 将它们保存到扩展存储区域中chrome.storage.local
  • 现在,您可以在弹出窗口中显示它们,在新
  • 选项卡中显示它们以进行编辑,或者其他任何内容
  • 如果你想在页面上以覆盖层的形式显示它们,只需在我们制作的javascript侦听器类中创建一个函数来执行此操作,并向它发送一条消息,其中包含要显示的图像

为了帮助您入门,这里有一个 JavaScript 侦听器类,我用来在我的扩展中做类似的事情。

(请注意,这依赖于John Resig的简单JavaScript继承,我强烈建议在编写类时使用(

// IMPORTANT NOTE you must reload your extension via chrome://extensions 
// AND reload the browser tab in order for changes to this file to be seen!!
var PageActionListener = Class.extend({
    /**
     * This class is meant to be injected into a webpage
     * once there, it listens for messages from an extension
     * messages must pass like {pageAction:"someAction", ... } 
     * where someAction should map to a function in this class
     * responses should take the form 
     * {success:true, pageAction:"someAction", data:"someData", ... }
     */
    attachListener: function() {
        /**
         * Attaches a chrome message listener to the current page
         * this allows the extension to call 
         * the functions in this class from the context of the page
         * and receive responses from those functions via messaging
         */
        var _this=this;
        // Listen for messages from the popup
        chrome.runtime.onMessage.addListener(function (msg, sender, extensionCallback) {
            // First, validate the message links to a function
            if (msg.pageAction) {
                // then make sure its a legit function in this class
                if(typeof _this[msg.pageAction] === "function"){
                    // call that fucntion
                    _this[msg.pageAction](msg,function(response){
                        extensionCallback(response);
                    });
                }
                else extensionCallback({success:false,msg:msg,error:"Action not found"});
                return true;
            }
        });
    },
    getImages:function(msg,callback){
        /**
         * Traverses the DOM looking for images and returning them
         * as an array of base64 strings
         * @param object msg The message that triggered this action
         * @param function callback A function to be called when the action below is complete
         * passes to callback the images gathered from the page
         */
        var images = [];
        var $images= $('img');
        $images.each(function(){
            var url = this.src;
            images.push(url);
        });
        // convert images to base64
        $.ajax({
            type: "POST",
            url: "https://somedomain.com/shared-resources/php/encodeImagesToBase64.php", // you'll need to update this to your path
            data: {urls:images},
            success: function(response) {
                response.msg=msg;
                send the response back to the extension
                callback(response);
            },
            error: function(xhr, status, error) {
                callback({success:false,msg:msg,error:error.Message})
            }
        });
    },
    // add other functions that need to be called by the extension here
});

以下是将图像转换为base64的encodeImagesToBase64.php的内容:

<?php
if (isset($_POST['urls']) ){
    $imageStrings=[];
    foreach($_POST['urls'] as $url){
        $imageStrings[]=base64_encode(file_get_contents($url));
    }
    echo json_encode(['success'=>true,'images'=>$imageStrings]);
}else{
    echo json_encode(['success'=>false,'error'=>'Error: No images to encode']);;
}

这是一个示例扩展,它可以满足您的需求。

它需要一种方法来满足你的实际需求,但是,它应该足以让你理解我上面提出的概念和方法。

注意:示例扩展使用托管在我的服务器上的encodeImagesToBase64.php副本,您需要托管自己的副本并使用其路径更新 ajax 调用。我暂时把我的留在那里,这样你就可以测试它,但不要指望它永远存在:)