İçerik komut dosyaları uzantı bağlamında değil, web sayfası bağlamında çalıştığından genellikle uzantının geri kalanıyla iletişim kurmanın bir yolunu bulmaları gerekir. Örneğin, bir RSS okuyucu uzantısı, bir sayfada RSS özet akışının varlığını algılamak için içerik komut dosyalarını kullanabilir ve ardından bu sayfa için bir sayfa işlemi simgesi görüntülemek üzere arka plan sayfasını bilgilendirebilir.
Uzantılar ve içerik komut dosyaları arasındaki iletişim, mesaj iletme yoluyla sağlanır. Her iki taraf da diğer uçtan gönderilen mesajları dinleyebilir ve aynı kanalda yanıt verebilir. Bir mesaj, geçerli herhangi bir JSON nesnesi (boş, Boole, sayı, dize, dizi veya nesne) içerebilir. Tek seferlik istekler için basit bir API ve paylaşılan bağlamda birden fazla mesaj alışverişi yapmak için uzun süreli bağlantılar oluşturmanıza olanak tanıyan daha karmaşık bir API vardır. Ayrıca, kimliğini biliyorsanız başka bir uzantıya mesaj göndermeniz de mümkündür. Bu konu, Uzantılar arası mesajlar bölümünde ele alınmıştır.
Basit tek seferlik istekler
Uzantınızın başka bir bölümüne yalnızca tek bir mesaj göndermeniz (ve isteğe bağlı olarak yanıt almanız) gerekiyorsa basitleştirilmiş runtime.sendMessage veya tabs.sendMessage yöntemini kullanmanız gerekir . Bu yöntem, içerik komut dosyasından uzantıya veya tam tersi yönde tek seferlik JSON serileştirilebilir mesaj göndermenize olanak tanır. İsteğe bağlı bir geri çağırma parametresi, varsa diğer taraftan gelen yanıtı işlemenize olanak tanır.
İçerik komut dosyasından istek gönderme işlemi şu şekilde görünür:
chrome.runtime.sendMessage({greeting: "hello"}, function(response) {
console.log(response.farewell);
});
Uzantıdan içerik komut dosyasına istek gönderme işlemi de çok benzerdir. Tek fark, isteğin hangi sekmeye gönderileceğini belirtmeniz gerektiğidir. Bu örnekte, seçili sekmedeki içerik komut dosyasına mesaj gönderme işlemi gösterilmektedir.
chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
chrome.tabs.sendMessage(tabs[0].id, {greeting: "hello"}, function(response) {
console.log(response.farewell);
});
});
Alıcı tarafta, mesajı işlemek için bir runtime.onMessage etkinlik işleyici ayarlamanız gerekir. Bu, içerik komut dosyasından veya uzantı sayfasından aynı şekilde görünür.
chrome.runtime.onMessage.addListener(
function(request, sender, sendResponse) {
console.log(sender.tab ?
"from a content script:" + sender.tab.url :
"from the extension");
if (request.greeting == "hello")
sendResponse({farewell: "goodbye"});
}
);
Yukarıdaki örnekte sendResponse eşzamanlı olarak çağrıldı. sendResponse işlevini eşzamansız olarak kullanmak istiyorsanız return true; işlevini onMessage etkinlik işleyicisine ekleyin.
sendResponse geri çağırma yalnızca eşzamanlı olarak kullanıldığında veya etkinlik işleyici, eşzamansız olarak yanıt vereceğini belirtmek için true döndürdüğünde geçerlidir. İşleyicilerden hiçbiri true değerini döndürmezse veya sendResponse geri çağırması çöp toplama işlemine tabi tutulursa sendMessage işlevinin geri çağırması otomatik olarak çağrılır.Uzun süreli bağlantılar
Bazen tek bir istek ve yanıttan daha uzun süren bir sohbet yapmak faydalı olabilir. Bu durumda, sırasıyla runtime.connect veya tabs.connect kullanarak içerik komut dosyanızdan bir uzantı sayfasına ya da tam tersi yönde uzun süreli bir kanal açabilirsiniz . Kanala isteğe bağlı olarak ad verilebilir. Bu sayede farklı bağlantı türlerini ayırt edebilirsiniz.
Bir kullanım alanı, otomatik form doldurma uzantısı olabilir. İçerik komut dosyası, belirli bir giriş için uzantı sayfasına bir kanal açabilir ve doldurulacak form verilerini istemek üzere sayfadaki her giriş öğesi için uzantıya bir mesaj gönderebilir. Paylaşılan bağlantı, uzantının içerik komut dosyasından gelen çeşitli mesajları birbirine bağlayan paylaşılan durumu korumasına olanak tanır.
Bağlantı oluşturulurken her uca, bu bağlantı üzerinden mesaj göndermek ve almak için kullanılan bir runtime.Port nesnesi verilir.
İçerik komut dosyasından kanal açma, mesaj gönderme ve mesaj dinleme adımları aşağıda açıklanmıştır:
var port = chrome.runtime.connect({name: "knockknock"});
port.postMessage({joke: "Knock knock"});
port.onMessage.addListener(function(msg) {
if (msg.question == "Who's there?")
port.postMessage({answer: "Madame"});
else if (msg.question == "Madame who?")
port.postMessage({answer: "Madame... Bovary"});
});
Uzantıdan içerik komut dosyasına istek gönderme işlemi de çok benzerdir. Tek fark, hangi sekmeye bağlanılacağını belirtmeniz gerekmesidir. Yukarıdaki örnekte bağlantı oluşturma çağrısını tabs.connect ile değiştirmeniz yeterlidir.
Gelen bağlantıları işlemek için bir runtime.onConnect etkinlik işleyicisi ayarlamanız gerekir. Bu, içerik komut dosyasından veya uzantı sayfasından aynı şekilde görünür. Uzantınızın başka bir bölümü "connect()" işlevini çağırdığında bu etkinlik, bağlantı üzerinden mesaj göndermek ve almak için kullanabileceğiniz runtime.Port nesnesiyle birlikte tetiklenir. Gelen bağlantılara yanıt verme işlemi şu şekilde görünür:
chrome.runtime.onConnect.addListener(function(port) {
console.assert(port.name == "knockknock");
port.onMessage.addListener(function(msg) {
if (msg.joke == "Knock knock")
port.postMessage({question: "Who's there?"});
else if (msg.answer == "Madame")
port.postMessage({question: "Madame who?"});
else if (msg.answer == "Madame... Bovary")
port.postMessage({question: "I don't get it."});
});
});
Bağlantı noktası ömrü
Bağlantı noktaları, uzantının farklı bölümleri arasında iki yönlü iletişim yöntemi olarak tasarlanır. Burada (üst düzey) bir çerçeve en küçük bölüm olarak kabul edilir. tabs.connect, runtime.connect veya runtime.connectNative çağrıldığında Port oluşturulur. Bu bağlantı noktası, postMessage aracılığıyla diğer uca mesaj göndermek için hemen kullanılabilir.
Bir sekmede birden fazla çerçeve varsa tabs.connect çağrıldığında runtime.onConnect etkinliği birden fazla kez çağrılır (sekmedeki her çerçeve için bir kez). Benzer şekilde, runtime.connect kullanılırsa onConnect etkinliği birden fazla kez tetiklenebilir (uzantı sürecindeki her çerçeve için bir kez).
Örneğin, her açık bağlantı noktası için ayrı bir durum tutuyorsanız bağlantının ne zaman kapatıldığını öğrenmek isteyebilirsiniz. Bunun için runtime.Port.onDisconnect etkinliğini dinleyebilirsiniz. Bu etkinlik, kanalın diğer tarafında geçerli bağlantı noktası olmadığında tetiklenir. Bu durum aşağıdaki koşullarda ortaya çıkar:
- Diğer uçta runtime.onConnect için dinleyici yoktur.
- Bağlantı noktasını içeren sekme kaldırılır (ör. sekmede geziniliyorsa).
connectadlı işlevin çağrıldığı çerçeve kaldırıldı.- Bağlantı noktası alan tüm çerçeveler (runtime.onConnect aracılığıyla) kaldırılmıştır.
- runtime.Port.disconnect, diğer uç tarafından çağrılır. Bir
connectçağrısı alıcının ucunda birden fazla bağlantı noktasıyla sonuçlanırsa ve bu bağlantı noktalarından herhangi birindedisconnect()çağrısı yapılırsaonDisconnectetkinliğinin yalnızca gönderenin bağlantı noktasında tetikleneceğini, diğer bağlantı noktalarında tetiklenmeyeceğini unutmayın.
Uzantılar arası mesajlaşma
Uzantınızdaki farklı bileşenler arasında mesaj göndermenin yanı sıra, diğer uzantılarla iletişim kurmak için Messaging API'yi de kullanabilirsiniz. Bu, diğer uzantıların yararlanabileceği genel bir API'yi kullanıma sunmanıza olanak tanır.
Gelen istekleri ve bağlantıları dinleme, runtime.onMessageExternal veya runtime.onConnectExternal yöntemlerini kullanmanız dışında dahili duruma benzer. Her biriyle ilgili bir örneği aşağıda görebilirsiniz:
// For simple requests:
chrome.runtime.onMessageExternal.addListener(
function(request, sender, sendResponse) {
if (sender.id == blocklistedExtension)
return; // don't allow this extension access
else if (request.getTargetData)
sendResponse({targetData: targetData});
else if (request.activateLasers) {
var success = activateLasers();
sendResponse({activateLasers: success});
}
});
// For long-lived connections:
chrome.runtime.onConnectExternal.addListener(function(port) {
port.onMessage.addListener(function(msg) {
// See other examples for sample onMessage handlers.
});
});
Benzer şekilde, başka bir uzantıya mesaj göndermek de uzantınız içinde mesaj göndermeye benzer. Tek fark, iletişim kurmak istediğiniz uzantının kimliğini iletmeniz gerektiğidir. Örneğin:
// The ID of the extension we want to talk to.
var laserExtensionId = "abcdefghijklmnoabcdefhijklmnoabc";
// Make a simple request:
chrome.runtime.sendMessage(laserExtensionId, {getTargetData: true},
function(response) {
if (targetInRange(response.targetData))
chrome.runtime.sendMessage(laserExtensionId, {activateLasers: true});
}
);
// Start a long-running conversation:
var port = chrome.runtime.connect(laserExtensionId);
port.postMessage(...);
Web sayfalarından mesaj gönderme
Uzantılar arası mesajlaşmaya benzer şekilde, uygulamanız veya uzantınız normal web sayfalarından gelen mesajları alıp yanıtlayabilir. Bu özelliği kullanmak için öncelikle manifest.json dosyanızda hangi web siteleriyle iletişim kurmak istediğinizi belirtmeniz gerekir. Örneğin:
"externally_connectable": {
"matches": ["*://*.example.com/*"]
}
Bu işlem, mesajlaşma API'sini belirttiğiniz URL kalıplarıyla eşleşen tüm sayfalara sunar. URL kalıbı en az bir ikinci düzey alan içermelidir. Yani "*", "*.com", "*.co.uk" ve "*.appspot.com" gibi ana makine adı kalıpları yasaktır. Web sayfasından, belirli bir uygulamaya veya uzantıya mesaj göndermek için runtime.sendMessage ya da runtime.connect API'lerini kullanın. Örneğin:
// The ID of the extension we want to talk to.
var editorExtensionId = "abcdefghijklmnoabcdefhijklmnoabc";
// Make a simple request:
chrome.runtime.sendMessage(editorExtensionId, {openUrlInEditor: url},
function(response) {
if (!response.success)
handleError(url);
});
Uygulamanız veya uzantınızdan, uzantılar arası mesajlaşmaya benzer şekilde runtime.onMessageExternal veya runtime.onConnectExternal API'leri aracılığıyla web sayfalarından gelen mesajları dinleyebilirsiniz. Yalnızca web sayfası bağlantı başlatabilir. Örnek:
chrome.runtime.onMessageExternal.addListener(
function(request, sender, sendResponse) {
if (sender.url == blocklistedWebsite)
return; // don't allow this web page access
if (request.openUrlInEditor)
openUrl(request.openUrlInEditor);
});
Yerel mesajlaşma
Uzantılar ve uygulamalar, yerel mesajlaşma ana makinesi olarak kaydedilen yerel uygulamalarla mesaj alışverişi yapabilir. Bu özellik hakkında daha fazla bilgi edinmek için Yerel mesajlaşma başlıklı makaleyi inceleyin.
Güvenlikle ilgili olarak göz önünde bulundurulması gerekenler
İçerik komut dosyaları daha az güvenilirdir
İçerik komut dosyaları, uzantı arka plan sayfasından daha az güvenilirdir (ör. kötü amaçlı bir web sayfası, içerik komut dosyalarının çalıştığı oluşturma işlemini tehlikeye atabilir). İçerik komut dosyasından gelen mesajların saldırgan tarafından oluşturulmuş olabileceğini varsayın ve tüm girişleri doğrulayıp temizlediğinizden emin olun. İçerik komut dosyasına gönderilen tüm verilerin web sayfasına sızabileceğini varsayın. İçerik komut dosyalarından alınan mesajlarla tetiklenebilecek ayrıcalıklı işlemlerin kapsamını sınırlayın.
Siteler arası komut dosyası çalıştırma
Bir içerik komut dosyasından veya başka bir uzantıdan mesaj alırken komut dosyalarınızın siteler arası komut dosyası çalıştırma saldırılarına karşı dikkatli olması gerekir. Bu tavsiye, uzantı arka plan sayfasında çalışan komut dosyalarının yanı sıra diğer web kaynaklarında çalışan içerik komut dosyaları için de geçerlidir. Özellikle aşağıdaki gibi tehlikeli API'leri kullanmaktan kaçının:
chrome.tabs.sendMessage(tab.id, {greeting: "hello"}, function(response) {
// WARNING! Might be evaluating an evil script!
var resp = eval("(" + response.farewell + ")");
});
chrome.tabs.sendMessage(tab.id, {greeting: "hello"}, function(response) {
// WARNING! Might be injecting a malicious script!
document.getElementById("resp").innerHTML = response.farewell;
});
Bunun yerine, komut dosyası çalıştırmayan daha güvenli API'leri tercih edin:
chrome.tabs.sendMessage(tab.id, {greeting: "hello"}, function(response) {
// JSON.parse does not evaluate the attacker's scripts.
var resp = JSON.parse(response.farewell);
});
chrome.tabs.sendMessage(tab.id, {greeting: "hello"}, function(response) {
// innerText does not let the attacker inject HTML elements.
document.getElementById("resp").innerText = response.farewell;
});
Örnekler
Mesajlar üzerinden iletişimle ilgili basit örnekleri examples/api/messaging dizininde bulabilirsiniz. Yerel mesajlaşma örneği, bir Chrome uygulamasının yerel bir uygulamayla nasıl iletişim kurabileceğini gösterir. Daha fazla örnek ve kaynak kodunu görüntüleme konusunda yardım için Örnekler'e bakın.