如何将元素数据提供给调试器脚本?

时间:2014-05-26 11:11:47

标签: javascript google-chrome-extension

我正在尝试为特定网站编写我的第一个Chrome扩展程序,自动下载网站加载的流。我已经使用chrome.debugger api下载了流,但现在我想使用网站上的数据自动命名流。

首先,让我给你相关的脚本:

manifest.json
---------------------------------------
{
"name": "Downloader script",
"description": "Downloads stuff",
"version": "0.1",
"permissions": [
"debugger",
"downloads"
],
"background": {
"scripts": ["background.js"]
},
"browser_action": {
"default_icon": "icon.png",
"default_title": "Downloader"
},
"manifest_version": 2
}

这是background.js,它显示一个窗口,说明已下载的所有文件。

background.js
--------------------------
chrome.browserAction.onClicked.addListener(function(tab) {
chrome.debugger.attach({tabId:tab.id}, version,
  onAttach.bind(null, tab.id));
});

var version = "1.0";

function onAttach(tabId) {
  if (chrome.runtime.lastError) {
    alert(chrome.runtime.lastError.message);
    return;
  }

  chrome.windows.create(
      {url: "headers.html?" + tabId, type: "popup", width: 400, height: 600});
}

以下是(非常简单的)headers.html:

<html>
<head>
<style>
body {
  font-family: monospace;
  word-wrap: break-word;
}

#container {
  white-space: pre;
}

.request {
  border-top: 1px solid black;
  margin-bottom: 10px;
}

</style>

<script src="headers.js"></script>
</head>

<body>
<div id="container"></div>
</body>
</html>

现在来了困难的部分,header.js

var tabId = parseInt(window.location.search.substring(1));

window.addEventListener("load", function() {
  chrome.debugger.sendCommand({tabId:tabId}, "Network.enable");
  chrome.debugger.onEvent.addListener(onEvent);
});

window.addEventListener("unload", function() {
  chrome.debugger.detach({tabId:tabId});
});

var requests = {};


function onEvent(debuggeeId, message, params) {
  if (tabId != debuggeeId.tabId)
    return;

  if (message == "Network.requestWillBeSent") {
    var requestDiv = requests[params.requestId];
    if (!requestDiv && params.redirectResponse) {
      var requestDiv = document.createElement("div");
      requestDiv.className = "request";
      requests[params.requestId] = requestDiv;
      downloadSong(params.requestId, params.redirectResponse);
    }
    document.getElementById("container").appendChild(requestDiv);
  }
}

function downloadSong(requestId, response) {
  var requestDiv = requests[requestId];
  var newSong = document.createElement("div");
  newSong.textContent = "New song is being downloaded...";
  var songLink = document.createElement('a');
  var songLinkText = document.createTextNode("Direct link to song");
  songLink.appendChild(songLinkText);
  songLink.title = "Right click -> save as...";
  songLink.href = response.headers.location;
  if (songLink.href.indexOf("//audio") > -1) {
    requestDiv.appendChild(newSong);
    requestDiv.appendChild(songLink);
    chrome.downloads.download({url: response.headers.location},function(id){});
  }
}

现在我从中获取流的网站具有以下结构:

<div id="trackInfo" class="unselectable">
    <div class="contents" style="display: block;">
        <div class="info">
            <div class="trackData">
                <div><a href="http://www.linktowebsite" class="songTitle" address="true">This is the song title i want to grab</a></div>
                <div><i class="byText">by</i> <a href="http://www.artistlink" class="artistSummary" address="true">Artist name i want to grab</a>
                </div>
                <div><i class="onText">on</i> <a class="albumTitle" address="true" href="http://www.albumlink" style="">Album title i want to grab</a></div>
            </div>
        </div>
    </div>
</div>

我的问题是:如何从页面中获取元素数据(我相信它被称为DOM)并将其与chrome.downloads api一起使用?由于headers.js文件(我认为)不与网页本身联系,只是网络部分。

PS:我第一次在这里发帖,我的帖子也会受到建设性的批评。

1 个答案:

答案 0 :(得分:0)

我有一种感觉,你在这里使用榴弹炮狩猎松鼠,使用"debugger"拦截网络请求并将DOM注入页面。

  • 为了拦截网络请求,有一个专用的API,chrome.webRequest

    您可以将监听器附加到chrome.webRequest.onBeforeRequest,您将获得与chrome.debugger.onEvent收听者中使用的信息相同的信息。

  • 为了注入您的DIV并从DOM读取数据,您(仅)需要content script

以下代码假设您还将使用jQuery(没有理由不这样做,用它来操作DOM更容易)。它只是骨架代码。

您可以指定内容脚本以始终加载音乐服务,并使用chrome.runtime.onMessage收听来自背景的消息:

chrome.runtime.onMessage.addListener(function(message) {
  if(message.songUrl){
    var newSong = $('<div>').text(New song is being downloaded...);
    /* fill the <div> and append it to the page */
  }
});

当您的后台检测到音乐流下载时,它会在请求事件中显示tabId,并且可以向所需的标签发送消息:

chrome.webRequest.onBeforeRequest.addListener(
  function(details){
    if (details.url.indexOf("//audio") > -1) {
      chrome.tabs.sendMessage(tabId, {songUrl: details.url});
    }
    return {}; // Do not modify the request
  },
  /* filter details */
);

至于提取歌曲细节,jQuery是你的朋友。你需要提出一个选择器来选择你需要的元素:

// Inside content script
var songName = $("#trackInfo .songTitle").text();
// etc.