2012-06-12 31 views
5

Tôi đang cố gắng để xác định một số cách để thiết lập một ID duy nhất cho các tab Chrome đáp ứng các điều kiện sau đây:Persistent ID duy nhất cho các tab Chrome kéo dài giữa các phiên trình duyệt

  • Độc đáo xác định mỗi tab
  • Lưu trú tương tự cho một tab nhất định giữa trình duyệt khởi động lại (tab được khôi phục theo phiên)
  • Vẫn giữ nguyên nếu tab bị đóng và sau đó mở lại với Hoàn tác tab đã đóng (Ctrl + Shift + T)
  • Vẫn phân biệt nếu tab bị trùng lặp

Tôi đã thực hiện một số nghiên cứu khá tích cực để tìm ra giải pháp toàn diện, nhưng không có gì có vẻ khá là lừa. Dưới đây là những phương pháp tôi đã cố gắng, để tăng tính hiệu quả:

  • tab.id cung cấp sử dụng Chrome: không tồn tại giữa các phiên trình duyệt hoặc đóng/undo-gần
  • Đặt một GUID trong cookie : không phải là duy nhất trên mỗi tab, chỉ có mỗi tên miền/URL
  • Đặt một GUID trong localStorage: vẫn tồn tại giữa các phiên trình duyệt và gần gũi/undo-gần, nhưng không phải là duy nhất trên mỗi tab, chỉ mỗi miền
  • Đặt GUID trong phiênStorage: duy nhất cho mỗi tab, vẫn tồn tại khi đóng/hoàn tác gần, duy nhất cho các tab trùng lặp, nhưng bị xóa giữa các phiên trình duyệt
  • Sử dụng thuộc tính tài liệu trang web có thể nhận dạng làm khóa duy nhất: đây là cách tiếp cận tốt nhất tôi đã tìm thấy cho đến nay. Một khóa có thể được tạo thông qua tập lệnh nội dung từ các giá trị sau: [location.href, document.referrer, history.length].

Về phương pháp cuối cùng này, khóa được tạo là duy nhất trên tất cả các tab có chung URL, liên kết giới thiệu và độ dài lịch sử. Các giá trị đó sẽ giữ nguyên cho một tab nhất định giữa trình duyệt khởi động lại/phiên khôi phục và đóng/hoàn tác đóng. Mặc dù khóa này "độc đáo", có những trường hợp không rõ ràng: ví dụ: 3 tab mới được mở cho http://www.google.com tất cả sẽ có cùng một điểm chung (và điều này thường xảy ra trong thực tế).

Phương pháp "đặt GUID trong sessionStorage" có thể được sử dụng để phân biệt giữa nhiều tab với cùng khóa được tạo cho các trường hợp đóng/đóng và trùng lặp trong phiên trình duyệt hiện tại. Nhưng điều này không giải quyết được vấn đề mơ hồ giữa khởi động lại trình duyệt.

Sự mơ hồ cuối cùng này có thể được giảm nhẹ trong quá trình khôi phục phiên bằng cách quan sát tab nào Chrome mở cùng nhau trong cửa sổ và ngoại suy cho khóa mơ hồ nhất định mà tab thuộc cửa sổ dựa trên sự hiện diện của các tab 'anh chị em' mong đợi trong phiên trình duyệt trước đó). Như bạn có thể tưởng tượng, việc triển khai giải pháp này khá tham gia và khá tinh ranh. Và nó chỉ có thể phân biệt giữa các tab có cùng khóa mà Chrome khôi phục vào các cửa sổ khác nhau. Điều đó để lại các tab có cùng khóa để khôi phục vào cùng một cửa sổ như không rõ ràng.

Có cách nào tốt hơn không? GUID duy nhất, được tạo bởi trình duyệt, mỗi tab được bảo đảm duy trì giữa các lần khởi động lại trình duyệt (khôi phục phiên) và đóng/hoàn tác đóng sẽ là lý tưởng nhưng cho đến nay tôi chưa tìm thấy bất kỳ thứ gì như thế này.

Trả lời

1

Nếu tôi hiểu đúng vấn đề của bạn, phương pháp thứ 5 của bạn nên làm như lừa, nhưng cùng với hai tiêu chí sau đây:

  • chrome.tabs.windowId (ID của cửa sổ tab được chứa trong)
  • chrome.tabs.index (Chỉ mục dựa trên zero của tab trong cửa sổ của nó)

Tất cả các giá trị này cần phải được lưu trữ bên trong tiện ích của bạn. Bên cạnh đó, bạn cũng sẽ phải mở rộng tiện ích mở rộng của mình lên chrome.tabs.onUpdated() và cập nhật tương ứng, khi các tab đang được kéo xung quanh, di chuyển qua các cửa sổ chủ sở hữu, v.v.

+0

Ý tưởng tuyệt vời. Thật không may windowId thay đổi giữa các phiên trình duyệt, nhưng nếu tôi có thể suy ra thay đổi cửa sổ giữa các phiên bằng cách ghi nhớ và so sánh tab nào trong mỗi cửa sổ trước và sau khi khởi động lại trình duyệt, tôi có thể sử dụng .index như bạn đề nghị phân biệt hai các tab giống hệt nhau trong một cửa sổ cụ thể. Cảm ơn nhiều. – joelpt

+0

Tôi sẽ thêm rằng tôi có thể tương quan với cửa sổ ghi nhớ "trước khi khởi động lại" với cửa sổ "sau khi khởi động lại" mở, nếu tôi có thể xác định bất kỳ tab * đơn * nào có url + referrer + historylength duy nhất. Vì tab đã nói là thẻ duy nhất có khóa cụ thể đó, tôi biết cửa sổ nào thuộc về nó; Do đó tôi biết rằng bất kỳ thẻ nhớ nào có cùng cửa sổ "cũ" cũng nằm trong cùng một cửa sổ "mới". – joelpt

+1

@joelpt yes, windowId không đáng tin cậy nhưng nếu bạn kết nối các trình nghe sự kiện 'chrome.window.onCreated' và' chrome.window.onRemoved', bạn có thể dễ dàng mô phỏng chỉ mục (id thứ tự) trên tất cả các cửa sổ. –

3

Câu hỏi ở đây thực hiện hầu hết công việc khám phá và câu trả lời được chấp nhận về cơ bản hoàn thành nó, nhưng vẫn còn một khoảng trống thực hiện lớn cho những người đang tìm cách triển khai một cái gì đó đòi hỏi ID thẻ liên tục. Tôi đã cố gắng để chưng cất điều này thành một triển khai thực tế.

Để tóm tắt: Tabs có thể được (gần như) duy nhất và liên tục được xác định theo yêu cầu của câu hỏi bằng cách duy trì một thanh ghi của các tab mà các cửa hàng kết hợp của các biến trong lưu trữ liên tục địa phương:

  • Tab.id
  • Tab.index
  • A 'dấu vân tay' của tài liệu mở trong tab - [location.href, document.referrer, history.length]

Các biến này có thể được theo dõi và lưu trữ trong registry bằng thính giả trên sự kết hợp của các sự kiện sau đây:

  • onUpdated
  • onCreated
  • onMoved
  • onDetached
  • onAttached
  • onRemoved
  • onReplaced

Vẫn còn cách để đánh lừa phương pháp này, nhưng trong thực tế chúng có thể khá hiếm - chủ yếu là các trường hợp cạnh.

Vì có vẻ như tôi không phải là người duy nhất cần giải quyết vấn đề này, tôi đã xây dựng triển khai của mình dưới dạng thư viện với ý định rằng nó có thể được sử dụng trong mọi tiện ích của Chrome. Đó là MIT được cấp phép và available on GitHub cho các yêu cầu tìm kiếm và kéo (trên thực tế, mọi phản hồi sẽ được hoan nghênh - chắc chắn có thể có những cải tiến).

1

Đặt này như một kịch bản nền tảng bền vững trong manifest.json:

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

Đây là background.js. Hy vọng mã sẽ tự giải thích.

var tabs_hashes = {}; 
var tabs_hashes_save_queued = false; 

function Start(){ 
    chrome.tabs.query({windowType: "normal"}, function(querytabs){ 
     querytabs.forEach(function(tab){ 
      tabs_hashes[tab.id] = GetHash(tab.url); 
     }); 

     if (localStorage.getItem("tabs_hashes") !== null){ 

      var ref_load = JSON.parse(localStorage["tabs_hashes"]); 
      var ref_tabId = {}; 


      querytabs.forEach(function(tab){ 
       for (var t = 0; t < ref_load.length; t++){ 
        if (ref_load[t][1] === tabs_hashes[tab.id]){ 
         ref_tabId[ref_load[t][0]] = tab.id; 
         ref_load.splice(t, 1); 
         break; 
        } 
       } 
      }); 

      // do what you have to do to convert previous tabId to the new one 
      // just use ref_tabId[your_previous_tabId] to get the current corresponding new tabId 
      console.log(ref_tabId); 

     } 
    }); 
} 


function SaveHashes(){ 
    if (!tabs_hashes_save_queued && Object.keys(tabs_hashes).length > 0){ 
     tabs_hashes_save_queued = true; 
     chrome.tabs.query({windowType: "normal"}, function(querytabs){ 
      var data = []; 
      querytabs.forEach(function(tab){ 
       if (tabs_hashes[tab.id]){ 
        data.push([tab.id, tabs_hashes[tab.id]]); 
       } else { 
        data.push([tab.id, GetHash(tab.url)]); 
       } 
      }); 
      localStorage["tabs_hashes"] = JSON.stringify(data); 
      setTimeout(function(){ tabs_hashes_save_queued = false; }, 1000); 
     }); 
    } 
} 

function GetHash(s){ 
    var hash = 0; 
    if (s.length === 0){ 
     return 0; 
    } 
    for (var i = 0; i < s.length; i++){ 
     hash = (hash << 5)-hash; 
     hash = hash+s.charCodeAt(i); 
     hash |= 0; 
    } 
    return Math.abs(hash); 
} 


chrome.tabs.onCreated.addListener(function(tab){ 
    SaveHashes(); 
}); 
chrome.tabs.onAttached.addListener(function(tabId){ 
    SaveHashes(); 
}); 
chrome.tabs.onRemoved.addListener(function(tabId){ 
    delete tabs_hashes[tabId]; 
    SaveHashes(); 
}); 
chrome.tabs.onDetached.addListener(function(tabId){ 
    SaveHashes(); 
}); 
chrome.tabs.onUpdated.addListener(function(tabId, changeInfo){ 
    if (changeInfo.pinned != undefined || changeInfo.url != undefined){ 
     delete tabs_hashes[tabId]; 
     SaveHashes(); 
    } 
}); 
chrome.tabs.onMoved.addListener(function(tabId){ 
    SaveHashes(); 
}); 
chrome.tabs.onReplaced.addListener(function(addedTabId, removedTabId){ 
    delete tabs_hashes[removedTabId]; 
    SaveHashes(); 
}); 


Start(); 

Tôi sử dụng mảng để lưu dữ liệu, vì theo cách này tôi có thể giữ thứ tự tab, rất có thể dữ liệu sẽ không được lưu trong đối tượng. Khi tải dữ liệu sau khi khởi động lại trình duyệt, ngay cả khi url không phải là duy nhất, tôi có thể tin tưởng rằng nó sẽ nằm dưới chỉ mục "đủ gần". Tôi sẽ làm điều đó phức tạp hơn, ví dụ như kiểm tra ngược lại nếu tab không được tìm thấy, nhưng điều này hoạt động ok cho đến nay.

Các vấn đề liên quan