【问题标题】:Is there a possible way to create screenshots of the whole screen out of a firefox extension?有没有办法从 Firefox 扩展中创建整个屏幕的屏幕截图?
【发布时间】:2012-04-18 13:03:08
【问题描述】:

我目前正在使用画布使用 JavaScript 创建屏幕截图并将它们编码为 base64。

但是,我目前的截图只包括实际网页,没有其他内容(没有地址栏等),我想知道是否可以实现全屏截图(任务栏和整个浏览器窗口等)以编程方式。

【问题讨论】:

  • 我认为不是,也不应该是,它非常不安全。您是否认为进入网站后他们正在收集有关您正在运行的程序(分析任务栏)等的信息?
  • 我可能需要给你一些关于我打算做什么的更多信息。我的公司有它自己的“重新”编程的 firefox 浏览器,我正在为此创建一个扩展。如果该浏览器打开的网站以配置的状态码(例如 404、500)响应,我的扩展程序会向监控服务器发送请求。除此之外,我应该发送带有错误的屏幕截图,效果很好,但我的公司希望看到整个浏览器窗口,而不仅仅是网站。 (我不知道原因,目前的版本可以,但我想知道是否有可能^^)
  • 也许浏览器支持但我怀疑但不能确定
  • 我也是,但我很好奇这是否根本不可能。我想他们只需要对页面本身感到满意。感谢您的尝试。
  • 给你:snipt.org/uhhz7 但之后你必须对其进行编码。希望它会帮助你。 :)

标签: javascript firefox-addon screenshot


【解决方案1】:

Firefox 没有此功能。您可以做的最好的事情是通过js-ctypes 使用操作系统功能。然而,这并不简单。无论如何,我需要 Windows API 的这段代码,所以它来了。首先您需要设置库、函数和数据类型:

Components.utils.import("resource://gre/modules/ctypes.jsm");

var userlib = ctypes.open("user32");
var gdilib = ctypes.open("gdi32");

var HWND = ctypes.voidptr_t;
var HGDIOBJ = ctypes.voidptr_t;
var HDC = HGDIOBJ;
var HBITMAP = HGDIOBJ;
var LPCTSTR = ctypes.unsigned_char.ptr;
var WORD = ctypes.uint16_t;
var DWORD = ctypes.uint32_t;

var SRCCOPY = 0xCC0020;

var BITMAPCOREHEADER = ctypes.StructType("BITMAPCOREHEADER", [
  {bcSize: DWORD},
  {bcWidth: WORD},
  {bcHeight: WORD},
  {bcPlanes: WORD},
  {bcBitCount: WORD}
]);

var GetDC = userlib.declare(
  "GetDC", ctypes.winapi_abi,
  HDC,
  HWND
);

var ReleaseDC = userlib.declare(
  "ReleaseDC", ctypes.winapi_abi,
  ctypes.int,
  HWND, HDC
);

var CreateCompatibleDC = gdilib.declare(
  "CreateCompatibleDC", ctypes.winapi_abi,
  HDC,
  HDC
);

var CreateCompatibleBitmap = gdilib.declare(
  "CreateCompatibleBitmap", ctypes.winapi_abi,
  HBITMAP,
  HDC, ctypes.int, ctypes.int
);

var DeleteObject = gdilib.declare(
  "DeleteObject", ctypes.winapi_abi,
  ctypes.bool,
  HGDIOBJ
);

var SelectObject = gdilib.declare(
  "SelectObject", ctypes.winapi_abi,
  HGDIOBJ,
  HDC, HGDIOBJ
);

var BitBlt = gdilib.declare(
  "BitBlt", ctypes.winapi_abi,
  ctypes.bool,
  HDC, ctypes.int, ctypes.int, ctypes.int, ctypes.int,
  HDC, ctypes.int, ctypes.int, DWORD
);

var GetDIBits = gdilib.declare(
  "GetDIBits", ctypes.winapi_abi,
  ctypes.int,
  HDC, HBITMAP, ctypes.unsigned_int, ctypes.unsigned_int,
  ctypes.unsigned_char.ptr, BITMAPCOREHEADER.ptr, ctypes.unsigned_int
);

现在是有趣的部分:

// The screen part we want to copy
var x = 0;
var y = 0;
var width = screen.width;
var height = screen.height;

// Create a bitmap/device context for the data
var screenDC = GetDC(null);
var dc = CreateCompatibleDC(screenDC);
var bitmap = CreateCompatibleBitmap(screenDC, width, height);

// Copy screen contents to bitmap
SelectObject(dc, bitmap);
BitBlt(dc, 0, 0, width, height, screenDC, x, y, SRCCOPY);

// Extract bitmap data
var bitmapHeader = new BITMAPCOREHEADER();
bitmapHeader.bcSize = BITMAPCOREHEADER.size;
bitmapHeader.bcWidth = width;
bitmapHeader.bcHeight = height;
bitmapHeader.bcPlanes = 1;
bitmapHeader.bcBitCount = 32;

var dataSize = width * height * 4;
var buffer = new ctypes.ArrayType(ctypes.unsigned_char, dataSize)();
GetDIBits(dc, bitmap, 0, height, buffer, bitmapHeader.address(), 0);

// Clean up
ReleaseDC(null, screenDC);
DeleteObject(dc);
DeleteObject(bitmap);

userlib.close();
gdilib.close();

// Draw data to the canvas
var canvas = document.getElementById("canvas");
canvas.setAttribute("width", width);
canvas.setAttribute("height", height);

var context = canvas.getContext("2d");
var imageData = context.createImageData(width, height);
for (var i = 0; i < height; i++)
{
  // Windows bitmaps are stored bottom-to-top, they are also using BGR0
  // byte order instead of RGBA. The data needs to be corrected here.
  var offset1 = i * width * 4;
  var offset2 = (height - 1 - i) * width * 4;
  for (var j = 0; j < width; j++)
  {
    imageData.data[offset1 + j * 4 + 0] = buffer[offset2 + j * 4 + 2];
    imageData.data[offset1 + j * 4 + 1] = buffer[offset2 + j * 4 + 1];
    imageData.data[offset1 + j * 4 + 2] = buffer[offset2 + j * 4 + 0];
    imageData.data[offset1 + j * 4 + 3] = 255;
  }
}
context.putImageData(imageData, 0, 0);

对于其他操作系统,您当然需要完全不同的代码。另一种方法是用你的扩展打包一个专门的 DLL 并通过 js-ctypes 使用它——这将允许用 C++ 编写相同的东西,这会稍微简单一些。

【讨论】:

  • 非常感谢您提供的代码!我想到了一个问题:我(在 developer.mozilla.org 上)读到 js-cytpes 库仅在 Gecko 2.0(FF 4.0)之后才可用。我们的浏览器是基于 FF 3.6... 我想我必须用 c++ 编写整个代码。
  • @Termi:Firefox 3.6 中的 js-ctypes 非常有限,当时它是一个实验性功能 - 它只能用于简单类型,甚至不能使用指针。所以是的,要么用 C++ 编写整个东西(一个可以通过 js-ctypes 调用的常规 DLL,不需要任何复杂的参数或 XPCOM 组件),要么将你的浏览器更新到一个不太过时的 Gecko 版本。
  • 坦克,我将不得不坚持使用 C++。正如我上面提到的,浏览器是我公司的,不会很快更新到新版本...
【解决方案2】:

否 - 如 cmets 所述的安全性。

您唯一能做的就是从文档信息(如 location.href)中获取您需要/可以获取的内容。将其添加为底部/顶部中的可见信息 => grap => 再次隐藏(如果用户应该继续工作)。

【讨论】:

  • 这个问题是关于 Firefox 扩展的 - 安全性不起作用。
【解决方案3】:

先按shift+F2 它会打开 firefox 控制台..give 命令screenshot --fullpage 并按回车键(用于整页)

screenshot(只针对可见部分)

你也可以通过tools->web developer->developer toolbar

来做到这一点

值得一试..最好不用扩展

【讨论】:

  • 首先,这个问题大约是15个月大。其次,您的解决方案与手头的问题无关,当时我需要在 Firefox 3.6 中以编程方式从扩展程序中创建屏幕截图。手动操作(这意味着客户必须这样做,而这在控制台上没有访问权限)不是一种选择。
  • 对不起@Termi 我认为它会在未来帮助其他用户..因此我提出了我的答案..虽然我没有彻底注意到你的问题......再次抱歉......没关系跨度>
猜你喜欢
  • 1970-01-01
  • 2012-12-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-02-04
相关资源
最近更新 更多