31

Sau khi tiện ích mở rộng của Chrome mà tôi đang thực hiện được cài đặt hoặc nâng cấp, tập lệnh nội dung (được chỉ định trong tệp kê khai) không được tiêm lại để yêu cầu làm mới trang làm cho công việc mở rộng. Có cách nào để buộc các tập lệnh được tiêm lại không?Chèn lại tập lệnh nội dung tiện ích mở rộng của Chrome sau khi nâng cấp hoặc cài đặt

Tôi tin rằng tôi có thể tiêm lại chúng một cách lập trình bằng cách xóa chúng khỏi tệp kê khai và sau đó xử lý các trang cần chèn vào trang nền, nhưng đây không phải là giải pháp tốt.

Tôi không muốn tự động làm mới tab của người dùng vì điều đó có thể mất một số dữ liệu của họ. Safari tự động làm mới tất cả các trang khi bạn cài đặt hoặc nâng cấp tiện ích mở rộng.

+0

Hình như Safari 7 (ít nhất) không còn tự động làm mới trang khi một phần mở rộng được cài đặt – baseten

Trả lời

20

Có một cách để cho phép một phần mở rộng nặng nội dung kịch bản để tiếp tục hoạt động sau khi nâng cấp, và làm cho nó hoạt động ngay lập tức sau khi cài đặt.

Install

Phương pháp cài đặt chỉ đơn giản là lặp qua tất cả các tab trong tất cả các cửa sổ, và tiêm một số kịch bản lập trình vào tab với các URL khớp.

Rõ ràng, bạn phải làm điều đó trong một kịch bản background page hoặc event page khai báo trong manifest.json:

"background": { 
    "scripts": ["background.js"] 
}, 

background.js:

// Add a `manifest` property to the `chrome` object. 
chrome.manifest = chrome.app.getDetails(); 

var injectIntoTab = function (tab) { 
    // You could iterate through the content scripts here 
    var scripts = chrome.manifest.content_scripts[0].js; 
    var i = 0, s = scripts.length; 
    for(; i < s; i++) { 
     chrome.tabs.executeScript(tab.id, { 
      file: scripts[i] 
     }); 
    } 
} 

// Get all windows 
chrome.windows.getAll({ 
    populate: true 
}, function (windows) { 
    var i = 0, w = windows.length, currentWindow; 
    for(; i < w; i++) { 
     currentWindow = windows[i]; 
     var j = 0, t = currentWindow.tabs.length, currentTab; 
     for(; j < t; j++) { 
      currentTab = currentWindow.tabs[j]; 
      // Skip chrome:// and https:// pages 
      if(! currentTab.url.match(/(chrome|https):\/\//gi)) { 
       injectIntoTab(currentTab); 
      } 
     } 
    } 
}); 

Upgrade

phương pháp

Việc nâng cấp dựa trên thực tế là các tập lệnh nội dung được tiêm trái sau khi một phần mở rộng bị tắt, gỡ cài đặt hoặc nâng cấp.

Khi kết nối cổng được thực hiện, bộ xử lý onDisconnect được thêm vào. Điều này chờ một giây sau sự kiện ngắt kết nối, sau đó thử kết nối lại. Nếu nó không thành công, một onDisconnect khác sẽ được kích hoạt để quá trình này xảy ra lần nữa, cho đến khi kết nối được thực hiện. Nó không hoàn hảo, nhưng nó hoạt động.

Các kịch bản nội dung:

var port; 

// Attempt to reconnect 
var reconnectToExtension = function() { 
    // Reset port 
    port = null; 
    // Attempt to reconnect after 1 second 
    setTimeout(connectToExtension, 1000 * 1); 
}; 

// Attempt to connect 
var connectToExtension = function() { 

    // Make the connection 
    port = chrome.runtime.connect({name: "my-port"}); 

    // When extension is upgraded or disabled and renabled, the content scripts 
    // will still be injected, so we have to reconnect them. 
    // We listen for an onDisconnect event, and then wait for a second before 
    // trying to connect again. Becuase chrome.runtime.connect fires an onDisconnect 
    // event if it does not connect, an unsuccessful connection should trigger 
    // another attempt, 1 second later. 
    port.onDisconnect.addListener(reconnectToExtension); 

}; 

// Connect for the first time 
connectToExtension(); 
+6

Tôi không chắc chắn điều này sẽ hoạt động nữa vì http://crbug.com/168263 ('Đừng để các tập lệnh nội dung mồ côi liên lạc với tiện ích mở rộng của chúng.'). 'chrome.runtime.sendMessage' không. Tôi có thể sai nhưng nếu mọi người gặp rắc rối thì sự thay đổi đó có lẽ là lý do tại sao. – vaughan

+1

trong chrome 46, bạn cần sử dụng 'chrome.runtime.getManifest()' thay vì 'chrome.manifest'. – Lee

+0

Để thực thi chrome.tabs.executeScript, bạn phải thêm quyền "tab", "http: // */*", "https: // */*" vào tệp manifest.json – cnmuc

15

Cách duy nhất để buộc tập lệnh nội dung được tiêm mà không làm mới trang là thông qua tiêm có lập trình.

Bạn có thể nhận tất cả các tab và chèn mã vào chúng bằng API tab chrome. Ví dụ: bạn có thể lưu trữ phiên bản tệp kê khai trong bộ nhớ cục bộ và mỗi lần kiểm tra xem phiên bản tệp kê khai có cũ hay không (trong trang nền), nếu bạn có thể nhận tất cả tab đang hoạt động và chèn mã của bạn theo chương trình hoặc bất kỳ giải pháp nào khác bạn chắc chắn rằng phần mở rộng được cập nhật.

Nhận tất cả các tab sử dụng:
chrome.tabs.query

và tiêm mã của bạn vào tất cả các trang
chrome.tabs.executeScript(tabId, {file: "content_script.js"});

+0

Cảm ơn, nhưng tôi không muốn sử dụng phương pháp này - tiêm theo chương trình đòi hỏi mã nhiều hơn và làm tăng độ phức tạp. –

+3

Tôi khá chắc chắn đó là cách duy nhất để làm điều đó. Tôi đã thực hiện một điều tương tự, bằng cách sử dụng cả tệp kê khai và tiêm chương trình để tất cả các tab được mở khi tập lệnh nền được tải lần đầu tiên được tiêm và tất cả các tab mới đều được xử lý bởi tệp kê khai thông thường. Tuy nhiên, điều bạn nên lưu ý là mọi thứ bạn để lại trong ngữ cảnh DOM hoặc trang cho ví dụ: tải lại hoặc nâng cấp, vì vậy bạn nên có một chức năng để hoàn tác mọi thứ bạn đã thực hiện, nhưng cũng cần phải có được bối cảnh mới để nói chuyện với bối cảnh cũ. –

+0

Cảm ơn @ AdamM-W - Tôi đã nghĩ những điều tương tự. Lý tưởng nhất là có một sự kiện có thể kích hoạt tập lệnh 'thoát' để hoàn tác tất cả thay đổi DOM. –

-5

bạn không thể thêm ?ver=2.10 vào cuối css hoặc js bạn nâng cấp?

"content_scripts": [ { 
     "css": [ "css/cs.css?ver=2.10" ], 
     "js": [ "js/contentScript.js?ver=2.10" ], 
     "matches": [ "http://*/*", "https://*/*" ], 
     "run_at": "document_end" 
    } ], 
Các vấn đề liên quan