2011-09-21 31 views
9

Tôi đang làm việc với một số mã cần chạy dưới dạng trang và nếu mã đang chạy dưới dạng Chrome Extension, tôi muốn có thể thực hiện các việc bổ sung. Những gì tôi đang sử dụng là:Phát hiện xem mã có đang chạy dưới dạng Tiện ích mở rộng của Chrome

<script> 
if (chrome && chrome.extension) { 
    // extension stuff 
} 
</script> 

Điều này có vẻ giống như một tốt capabilitydetection. Sử dụng chuỗi tác nhân người dùng gây ra rắc rối cho tôi vì nó giống nhau bất kể ngữ cảnh (trang web so với tiện ích mở rộng).

Câu hỏi: có kỹ thuật đáng tin cậy nào khác để phát hiện xem một đoạn mã có đang chạy bên trong tiện ích của Chrome không?

Cập nhật: Tôi tự hỏi nếu có điều gì tôi có thể đưa vào tệp manifest.json của mình để tôi có thể đọc lại. Lưu ý rằng tiện ích mở rộng mà tôi đang làm không phải là thứ liên tục chạy mọi lúc, đó là ứng dụng nội dung chạy trong một cửa sổ hoặc tab trình duyệt và không cần tương tác với các cửa sổ hoặc tab khác hoặc bất kỳ thứ gì khác .

+1

Bạn đồng hãy thử và nhận các chuỗi được quốc tế hóa, mặc dù việc kiểm tra trạng thái tiện ích mở rộng không phải là mục đích dự định của nó: http://code.google.com/chrome/extensions/i18n.html –

Trả lời

18

Rất nhiều câu trả lời phức tạp của cô ấy e, trong khi bạn có thể dễ dàng phát hiện xem bạn đang chạy trong một phần mở rộng của Chrome bằng cách kiểm tra sự tồn tại và không trống rỗng của chrome.runtime.id:

if (window.chrome && chrome.runtime && chrome.runtime.id) { 
    // Code running in a Chrome extension (content script, background page, etc.) 
} 
+1

Điểm tuyệt vời. 'chrome.runtime' đã được phát hành như một phần của Chrome 22 (https://developer.chrome.com/extensions/runtime#property-id) phát hành ngày 25 tháng 9 năm 2012 (http://googlechromereleases.blogspot.com/2012/09/stable-channel-update_25.html) ... một năm sau khi câu hỏi và câu trả lời được chấp nhận đã được đăng. Tôi đang cập nhật câu trả lời được chấp nhận. Cảm ơn bạn đã khai quật! – artlung

+0

trong cả hai trường hợp, điều kiện là đúng, hoặc chúng tôi kiểm tra từ bên trong cửa sổ bật lên tiện ích hoặc trong chế độ xem trang của trình duyệt. –

4

Thực tế đó là một cách tiếp cận tốt. Về mặt lý thuyết (không chắc chắn nếu điều này có liên quan hay không, ví dụ như có thể cung cấp các lỗ hổng) nó có thể được giả mạo rất dễ dàng. Tôi cho rằng nó phụ thuộc vào ngữ cảnh của bạn.

Dưới đây là một ý tưởng hơi mạnh:

if (chrome && 
    chrome.windows && 
    chrome.windows.get && 
    typeof chrome.windows.get === 'function' && 
    chrome.windows.get.toString() === 'function get() { [native code] }') 

Ý tưởng là giống như bạn, mặc dù nó hơi mạnh hơn, kể từ AFAIK có một đối tượng là một chức năng và có nó toString() giá trị có giá trị đó là không thể vì nó không hợp lệ cú pháp, vì vậy ngay cả khi cố gắng giả mạo giá trị đó sẽ không hoạt động trừ khi bạn thay đổi mã gốc (yêu cầu cấp độ hoàn toàn khác của hacker).

Đừng quên nếu kiểm tra những thứ như thế này yêu cầu quyền hay không, nhưng ý tưởng rõ ràng là tôi hy vọng.

CẬP NHẬT

Tôi chỉ nhận ra rằng "có nguồn gốc mã" cú pháp ý tưởng có thể bị lừa, bởi aliasing một chức năng hiện có. Ví dụ.

var FakeFn = Object.create; 
FakeFn.toString(); // "function create() { [native code] }" 

Nhưng có thể được quan tâm bằng cách chọn cẩn thận chức năng chúng tôi sử dụng, vì tên xuất hiện trong chuỗi. get có lẽ là quá phổ biến, nhưng nếu chúng ta có một tên hàm tối nghĩa (như captureVisibleTab của) được triển khai chỉ trong phần mở rộng chrome, nó vẫn là một giải pháp rất di động, vì không giống như kiểm tra cơ bản nơi mã có thể bị lừa bởi người dùng cục bộ khác mã, nó được biết trước rằng các trình duyệt không thực hiện bất kỳ chức năng gốc với tên này, do đó, nó vẫn an toàn trong tất cả các trình duyệt và với tất cả các mã người dùng.

CẬP NHẬT

Như @Mathew chỉ ra, ý tưởng này là foolable (mặc dù dường như chỉ cố). Tôi nghĩ rằng tôi có thể vá vấn đề bằng cách so sánh với Function.prototype.toString nhưng thấy rằng thậm chí có thể bị lừa bằng cách đánh dấu phương thức gốc toString và tạo một phương thức mới cho một số hàm trả về chuỗi sai và cho các hàm khác trả về chuỗi gốc.Tóm lại, ý tưởng của tôi hơi mạnh hơn bản gốc, trong đó nó sẽ loại trừ tất cả khả năng xảy ra va chạm không chủ ý (hơi hơn ý tưởng của OP), nhưng chắc chắn không phòng thủ chống lại một cuộc tấn công nguy hiểm như tôi nghĩ lúc đầu có thể là.

+0

Thú vị và hoạt động như mong đợi nhưng tôi không bị thuyết phục nó di động hơn tôi. Tôi tự hỏi nếu có một cái gì đó tôi có thể đưa vào tập tin 'manifest.json' của tôi mà tôi có thể đọc lại bằng cách nào đó. Cảm ơn cho chiming in – artlung

+1

@artlung, bất kỳ cách tiếp cận như vậy là ít di động hơn tôi, hãy để tôi giải thích: Toàn bộ API mở rộng (AFAIK, tôi thừa nhận không phải là rất chuyên gia về API) là javascript dựa. Vì vậy, tất cả các cuộc gọi sẽ phù hợp với các tiêu chuẩn JS, và sẽ có dạng 'obj.ref.fn()' thông thường, theo định nghĩa có thể bị lừa. Lý do cách tiếp cận của tôi là di động hơn là bởi vì nó không thể bị lừa. Bạn không thể tạo đối tượng vượt qua các điều kiện đó trừ khi bạn giả mạo chính trình duyệt, trong khi tôi có thể dễ dàng tạo 'window.chrome = {extension: true}' trong bất kỳ trình duyệt nào và mã của bạn sẽ nghĩ đó là tiện ích mở rộng của chrome. – davin

+0

Bạn có một điểm tuyệt vời. Tôi nghĩ rằng ý định của tôi không phải là cứng nhắc thực thi không giả mạo, nhưng chỉ đơn giản là phân biệt giữa việc sử dụng đơn giản của Chrome (và nhiều biến thể) và được mã hóa như một phần của extenson. Cảm ơn bạn rất nhiều vì những suy nghĩ cẩn thận đưa vào điều này! – artlung

2

Tôi biết điều này là cũ, nhưng chỉ nghĩ rằng tôi sẽ cung cấp một thay thế. Bạn có thể thêm một tệp javascript khác vào phần mở rộng chrome, vì vậy nó chứa hai tệp .js. manifest.json sẽ có:

"js": ["additionalscript.js", "yourscript.js"] 

Các additionalscript.js chỉ đơn giản là có thể khai báo một biến var isextension = true. yourscript.js có thể kiểm tra typeof isextension != 'undefined'.

Nhưng có lẽ một ví dụ thú vị hơn, nó có thể tuyên bố

var adminpassword='letmein' 

Bây giờ yourscript.js chỉ có quyền truy cập vào adminpassword khi chạy trong phần mở rộng.

(Tất nhiên bạn sẽ không nhúng một mật khẩu trong một tập tin kịch bản nếu các plugin là trên một máy mà có thể bị tổn hại)

+0

Tôi nghĩ bạn có nghĩa là 'tập lệnh' không phải là 'js'. Bạn sẽ luôn muốn làm bài kiểm tra như 'typeof isextension! = 'Undefined'' hoặc bạn sẽ nhận được một ngoại lệ JavaScript khi tệp bổ sung không được thực thi. Bạn cũng nên lưu ý rằng đây là phần 'nền' của tệp kê khai. –

+0

Cảm ơn @DanMcGrath - Tôi có phần "content_scripts" của tệp manifest.json có mục nhập "js": "content_scripts": [ { "đối sánh": ["*: //*.google.com/* "], " js ": [" One.js "," Two.js "] } ]. Và tốt kiểm tra lại điểm cho undefined –

1

tôi nhận thấy rằng trong Chrome, đối tượng chrome, đó là tài sản của cửa sổ toàn cầu không thể xóa đối tượng. Nếu đó là thao tác xóa thuộc tính do người dùng định nghĩa thì thành công. Vì vậy, bạn có thể kiểm tra theo cách này:

var isRunningInExtension = (!(delete window.chrome) && chrome.extension) ? 
          true : false; 

UPDATE: Đường dây trên không thực sự đảm bảo mã đang chạy trong phần mở rộng chrome. Mọi người có thể tạo một đối tượng được gọi là 'chrome' với thuộc tính 'extension' và sau đó đóng băng/đóng dấu đối tượng đó - thực hiện việc này sẽ đủ để vượt qua kiểm tra và có kết quả không chính xác rằng mã của bạn đang chạy bên trong tiện ích chrome.

Đảm bảo bạn đang chạy mã trong tiện ích mở rộng, bạn phải kiểm tra đối tượng chrome toàn cục trước khi javascript bất kỳ được chạy - theo cách đó bạn sẽ đảm bảo rằng không có đối tượng chrome giả nào được tạo trước khi thử nghiệm.

Một giải pháp có thể là sử dụng khung nội tuyến - trong ví dụ bên dưới tôi sử dụng thuộc tính hộp cát của iframe để hướng dẫn iframe không thực thi bất kỳ tập lệnh nào (kể cả tập lệnh kèm theo thẻ tập lệnh) - theo cách đó tôi có thể đảm bảo không có tập lệnh nào có thể sửa đổi đối tượng window.chrome chung.

(function() { 
    var isChromeExtension = (function() { 
    var contentWindow, 
     iframe = document.createElement("iframe"), 
     isChromeExtension; 
    // test for sandbox support. It is supported in most recent version of Chrome 
    if ("sandbox" in iframe) { 
     try { 
     iframe.sandbox = "allow-same-origin"; 
     iframe.src=location.href; 
     iframe.style="display: none"; 
     document.body.appendChild(iframe); 
     contentWindow = iframe.contentWindow; 
     isChromeExtension = !!(contentWindow.chrome && contentWindow.chrome.extension); 
     document.body.removeChild(iframe); 
     } catch(e) {} 
    } 
    return isChromeExtension; 
    }()); 
}()); 

kết quả có thể là:

  • đúng - nếu mã đang chạy bên trong một phần mở rộng của Chrome
  • sai - nếu mã không chạy bên trong một phần mở rộng của Chrome
  • không xác định - nếu trình duyệt không hỗ trợ hộp cát cho iframe hoặc một số lỗi xảy ra trong khi thử nghiệm
+0

Nó không phải là rõ ràng với tôi rằng sự hiểu biết của bạn về cách 'xóa' công trình là như bạn nói. Tôi cũng có thể tạo một đối tượng, nói 'window.g = {x: 1}' và chạy xóa trên nó và nhận được kết quả tương tự sai khi cố xóa nó. ... có thể là một ví dụ đầy đủ hơn về công việc này là cần thiết. – artlung

+0

Phương pháp mới của bạn không thực sự hiệu quả, và cũng không phải là bằng chứng ngu ngốc. Nếu môi trường thực sự độc hại, thì bất kỳ đối tượng nào, bao gồm cả 'tài liệu' có thể bị giả mạo. Không có cách nào để bảo vệ chống lại điều đó, vì vậy bạn nên thay vì sử dụng phương pháp dễ đọc nhất và dễ hiểu nhất. –

+0

Thực sự không thực sự lắm - nó tải toàn bộ trang/kiểu/tập lệnh vào khung nội tuyến, nhưng không có tập lệnh nào được thực thi (nội tuyến hoặc kèm theo thẻ tập lệnh) - đó là vai trò của hộp cát - vì vậy không có cách nào từ phía máy khách để thay đổi các đối tượng toàn cầu và thậm chí bắt chước đối tượng tài liệu. Hãy nhớ rằng không thể xóa đối tượng chrome nhưng mọi người có thể ghi đè nó - vì vậy, tôi có thể thực hiện như sau: 'window.chrome = {runtime: {id: {}}};' và câu trả lời được đề xuất của bạn sẽ nói rằng mã của tôi đang chạy bên trong một phần mở rộng, trong khi đó là không đúng sự thật. – ttsvetkov

1

Chrome không cung cấp bất kỳ API trực tiếp để kiểm tra tình trạng hoạt động của ứng dụng đó là nó đang chạy trong cửa sổ bật lên mở rộng hoặc trong chế độ xem trang chrome.tuy nhiên, một thủ thuật gián tiếp có thể làm việc là chúng ta có thể khớp với độ phân giải của phần mở rộng bằng hoặc nhỏ hơn như được chỉ định trong CSS (trong trường hợp này, cửa sổ mở rộng sẽ mở) hoặc lớn hơn (trong trường hợp này, xem trang web sẽ là mở).

1

Tôi có nhu cầu tương tự.

Nhưng tôi không cần quan tâm đến các trang web cố gắng lừa mã.

const SCRIPT_TYPE = (() => { 
    if (chrome && chrome.extension && chrome.extension.getBackgroundPage && chrome.extension.getBackgroundPage() === window) { 
     return 'BACKGROUND'; 
    } else if (chrome && chrome.extension && chrome.extension.getBackgroundPage && chrome.extension.getBackgroundPage() !== window) { 
     return 'POPUP'; 
    } else if (!chrome || !chrome.runtime || !chrome.runtime.onMessage) { 
     return 'WEB'; 
    } else { 
     return 'CONTENT'; 
    } 
})(); 

Trên đây nên phát hiện 4 kịch bản

  • javascript được chạy trong một trang nền
  • javascript được chạy trong một trang popup
  • javascript được chạy trong một kịch bản bối cảnh
  • javascript được chạy trực tiếp trên trang web
Các vấn đề liên quan