Bản dùng thử theo nguyên gốc cho phần tử HTML <permission> mới

Có một số phương thức bắt buộc để yêu cầu quyền sử dụng các tính năng mạnh mẽ như quyền truy cập thông tin vị trí trong ứng dụng web. Các phương thức này có một số thách thức, đó là lý do nhóm quyền của Chrome đang thử nghiệm một phương thức khai báo mới: một phần tử <permission> HTML chuyên dụng. Phần tử này đang trong giai đoạn thử nghiệm theo nguyên gốc từ Chrome 126 và cuối cùng, chúng tôi hy vọng có thể chuẩn hoá phần tử này.

Phương thức bắt buộc để yêu cầu cấp quyền

Khi cần quyền truy cập vào các tính năng mạnh mẽ, ứng dụng web cần phải yêu cầu cấp quyền. Ví dụ: khi Google Maps yêu cầu vị trí của người dùng bằng cách sử dụng API Vị trí địa lý, trình duyệt sẽ nhắc người dùng, thường là với lựa chọn lưu trữ quyết định đó. Đây là một khái niệm được xác định rõ ràng trong quy cách về Quyền.

Yêu cầu ngầm ẩn trong lần sử dụng đầu tiên so với yêu cầu rõ ràng trước

API Vị trí địa lý là một API mạnh mẽ và dựa vào phương pháp hỏi ngầm khi sử dụng lần đầu. Ví dụ: khi một ứng dụng gọi phương thức navigator.geolocation.getCurrentPosition(), lời nhắc cấp quyền sẽ tự động bật lên trong lệnh gọi đầu tiên. Một ví dụ khác là navigator.mediaDevices.getUserMedia().

Các API khác, chẳng hạn như Notification API (API thông báo) hoặc Device Orientation and Motion API (API chuyển động và hướng thiết bị), thường có cách rõ ràng để yêu cầu quyền thông qua một phương thức tĩnh như Notification.requestPermission() hoặc DeviceMotionEvent.requestPermission().

Những thách thức với phương thức bắt buộc để yêu cầu cấp quyền

Yêu cầu quyền rác

Trước đây, các trang web có thể gọi các phương thức như navigator.mediaDevices.getUserMedia() hoặc Notification.requestPermission(), nhưng cũng có thể gọi navigator.geolocation.getCurrentPosition() ngay khi tải trang web. Một lời nhắc cấp quyền sẽ bật lên trước khi người dùng tương tác với trang web. Đôi khi, điều này được mô tả là yêu cầu cấp quyền rác và ảnh hưởng đến cả hai phương pháp, tức là yêu cầu ngầm ẩn khi sử dụng lần đầu cũng như yêu cầu rõ ràng ngay từ đầu.

Lời nhắc cấp quyền truy cập vào micrô xuất hiện khi tải một trang web.

Các biện pháp giảm thiểu của trình duyệt và yêu cầu về cử chỉ của người dùng

Tình trạng yêu cầu cấp quyền không hợp lệ đã khiến các nhà cung cấp trình duyệt yêu cầu một cử chỉ của người dùng như nhấp vào nút hoặc sự kiện nhấn phím trước khi hiển thị lời nhắc cấp quyền. Vấn đề với phương pháp này là trình duyệt rất khó, nếu không muốn nói là không thể, xác định xem một cử chỉ cụ thể của người dùng có dẫn đến việc hiển thị lời nhắc cấp quyền hay không. Có thể người dùng chỉ đang nhấp vào trang một cách bực bội ở bất cứ đâu vì trang mất quá nhiều thời gian để tải, hoặc có thể họ thực sự đang nhấp vào nút Tìm tôi. Một số trang web cũng rất giỏi trong việc lừa người dùng nhấp vào nội dung để kích hoạt lời nhắc.

Một biện pháp giảm thiểu khác là thêm các biện pháp giảm thiểu hành vi lạm dụng lời nhắc, chẳng hạn như chặn hoàn toàn các tính năng để bắt đầu hoặc hiển thị lời nhắc cấp quyền theo cách không theo phương thức cửa sổ bật lên và ít xâm phạm hơn.

Trình duyệt Chrome hiển thị

Xác định quyền theo ngữ cảnh

Một thách thức khác, đặc biệt là trên màn hình lớn, là cách lời nhắc cấp quyền thường hiển thị: phía trên đường chết, tức là bên ngoài khu vực cửa sổ trình duyệt mà ứng dụng có thể vẽ lên. Không phải là hiếm khi người dùng bỏ lỡ lời nhắc ở đầu cửa sổ trình duyệt khi họ chỉ nhấp vào một nút ở cuối cửa sổ. Vấn đề này thường trở nên trầm trọng hơn khi các biện pháp giảm thiểu nội dung rác trên trình duyệt được áp dụng.

Google Maps đang mở lời nhắc cấp quyền truy cập thông tin vị trí. Nút cấp quyền truy cập thông tin vị trí đã kích hoạt lời nhắc ở quá xa.

Không thể dễ dàng huỷ bỏ

Cuối cùng, người dùng rất dễ bị lạc đường. Ví dụ: sau khi người dùng chặn quyền truy cập vào một tính năng, họ cần phải biết về trình đơn thả xuống thông tin trang web để có thể Đặt lại quyền hoặc bật lại các quyền đã bị chặn. Trong trường hợp xấu nhất, cả hai tuỳ chọn đều yêu cầu tải lại toàn bộ trang cho đến khi chế độ cài đặt mới cập nhật có hiệu lực. Các trang web không thể cung cấp lối tắt dễ dàng để người dùng thay đổi trạng thái quyền hiện có và phải giải thích cẩn thận cho người dùng cách thay đổi chế độ cài đặt như ở cuối ảnh chụp màn hình Google Maps sau.

Các chế độ kiểm soát trang web của Chrome trên Google Maps để thu hồi quyền.

Nếu quyền là yếu tố chính trong trải nghiệm, chẳng hạn như quyền truy cập vào micrô cho ứng dụng hội nghị truyền hình, thì các ứng dụng như Google Meet sẽ hiển thị hộp thoại xâm phạm để hướng dẫn người dùng cách bỏ chặn quyền.

Hướng dẫn của Google Meet về cách mở chế độ kiểm soát trang web của Chrome.

Phần tử <permission> khai báo

Để giải quyết những thách thức được mô tả trong bài đăng này, nhóm quyền của Chrome đã triển khai một thử nghiệm gốc cho một phần tử HTML mới, <permission>. Phần tử này cho phép nhà phát triển yêu cầu cấp quyền một cách rõ ràng để sử dụng một nhóm nhỏ các tính năng mạnh mẽ hiện có cho trang web. Ở dạng đơn giản nhất, bạn sử dụng thuộc tính này như trong ví dụ sau:

<permission type="camera" />

Chúng tôi vẫn đang dùng nhiều phương pháp để tranh luận về việc liệu <permission> có phải là phần tử rỗng hay không. Phần tử rỗng là phần tử tự đóng trong HTML không thể có nút con nào. Trong HTML, điều này có nghĩa là phần tử này có thể không có thẻ kết thúc.

Thuộc tính type

Thuộc tính type chứa danh sách các quyền mà bạn đang yêu cầu, được phân tách bằng dấu cách. Tại thời điểm viết bài này, các giá trị được phép là 'camera', 'microphone'camera microphone (được phân tách bằng dấu cách). Theo mặc định, phần tử này hiển thị tương tự như các nút có kiểu tác nhân người dùng cơ bản.

Các nút thành phần quyền khác nhau có quyền truy cập vào máy ảnh, micrô và quyền truy cập vào cả máy ảnh và micrô.

Thuộc tính type-ext

Đối với một số quyền cho phép thêm thông số, thuộc tính type-ext chấp nhận các cặp khoá-giá trị được phân tách bằng dấu cách, chẳng hạn như precise:true cho quyền truy cập thông tin vị trí địa lý.

Thuộc tính lang

Văn bản nút do trình duyệt cung cấp và phải nhất quán, vì vậy, bạn không thể tuỳ chỉnh trực tiếp văn bản này. Trình duyệt thay đổi ngôn ngữ của văn bản dựa trên ngôn ngữ kế thừa của tài liệu hoặc chuỗi phần tử mẹ hoặc thuộc tính lang không bắt buộc. Điều này có nghĩa là nhà phát triển không cần tự bản địa hoá phần tử <permission>. Nếu phần tử <permission> tiến xa hơn giai đoạn thử nghiệm gốc, thì một số chuỗi hoặc biểu tượng có thể được hỗ trợ cho mỗi loại quyền để tăng tính linh hoạt. Nếu bạn quan tâm đến việc sử dụng phần tử <permission> và cần một chuỗi hoặc biểu tượng cụ thể, hãy liên hệ!

Hành vi

Khi người dùng tương tác với phần tử <permission>, họ có thể luân phiên qua nhiều giai đoạn:

  • Nếu trước đây chưa cho phép một tính năng, họ có thể cho phép tính năng đó mỗi khi truy cập hoặc cho phép tính năng đó cho lần truy cập hiện tại.

    Lời nhắc cấp quyền để cho phép một tính năng lần này hoặc mỗi khi truy cập.

  • Nếu đã cho phép tính năng này trước đó, họ có thể tiếp tục cho phép hoặc ngừng cho phép.

    Lời nhắc cấp quyền để tiếp tục cho phép hoặc ngừng cho phép.

  • Nếu trước đây đã không cho phép một tính năng, thì họ có thể tiếp tục không cho phép hoặc cho phép tính năng đó lần này.

    Lời nhắc cấp quyền để tiếp tục không cho phép hoặc cho phép lần này.

Văn bản của phần tử <permission> sẽ tự động cập nhật dựa trên trạng thái. Ví dụ: nếu bạn được cấp quyền sử dụng một tính năng, thì văn bản sẽ thay đổi để cho biết tính năng đó được cho phép. Nếu trước tiên cần cấp quyền, văn bản sẽ thay đổi để mời người dùng sử dụng tính năng. So sánh ảnh chụp màn hình trước đó với ảnh chụp màn hình sau để xem hai trạng thái.

Nút cấp quyền có văn bản

Thiết kế CSS

Để đảm bảo người dùng có thể dễ dàng nhận ra nút này là một giao diện để truy cập vào các tính năng mạnh mẽ, kiểu của phần tử <permission> sẽ bị hạn chế. Nếu các quy tắc hạn chế về kiểu không phù hợp với trường hợp sử dụng của bạn, chúng tôi rất muốn biết lý do và cách thức! Mặc dù không thể đáp ứng tất cả nhu cầu tạo kiểu, nhưng chúng tôi hy vọng có thể khám phá ra các cách an toàn để cho phép tạo kiểu nhiều hơn cho phần tử <permission> sau khi thử nghiệm nguồn gốc. Bảng sau đây trình bày chi tiết một số thuộc tính có các quy tắc hạn chế hoặc quy tắc đặc biệt áp dụng cho chúng. Trong trường hợp vi phạm bất kỳ quy tắc nào, phần tử <permission> sẽ bị tắt và không thể tương tác. Mọi nỗ lực tương tác với lớp này sẽ dẫn đến các trường hợp ngoại lệ có thể được phát hiện bằng JavaScript. Thông báo lỗi sẽ chứa thêm thông tin chi tiết về lỗi vi phạm đã phát hiện.

Thuộc tính Quy tắc

color, background-color

Có thể dùng để đặt màu văn bản và màu nền tương ứng. Độ tương phản giữa hai màu cần đủ để văn bản dễ đọc (tỷ lệ tương phản tối thiểu là 3). Kênh alpha phải là 1.

font-size, zoom

Phải được đặt trong phạm vi tương đương với smallxxxlarge. Nếu không, phần tử sẽ bị vô hiệu hoá. Tính năng thu phóng sẽ được tính đến khi tính toán font-size.

outline-offset

Các giá trị âm sẽ được sửa thành 0.
margin (tất cả) Các giá trị âm sẽ được sửa thành 0.

font-weight

Các giá trị dưới 200 sẽ được sửa thành 200.

font-style

Các giá trị khác với normalitalic sẽ được sửa thành normal.

word-spacing

Các giá trị lớn hơn 0.5em sẽ được sửa thành 0.5em. Các giá trị dưới 0 sẽ được sửa thành 0.

display

Các giá trị không phải inline-blocknone sẽ được sửa thành inline-block.

letter-spacing

Các giá trị lớn hơn 0.2em sẽ được sửa thành 0.2em. Các giá trị dưới -0.05em sẽ được chỉnh sửa thành -0.05em.

min-height

Sẽ có giá trị mặc định là 1em. Nếu bạn cung cấp, giá trị tối đa được tính toán giữa giá trị mặc định và giá trị được cung cấp sẽ được xem xét.

max-height

Sẽ có giá trị mặc định là 3em. Nếu được cung cấp, giá trị tính toán tối thiểu giữa giá trị mặc định và giá trị được cung cấp sẽ được xem xét.

min-width

Sẽ có giá trị mặc định là fit-content. Nếu được cung cấp, giá trị được tính toán tối đa giữa giá trị mặc định và giá trị được cung cấp sẽ được xem xét.

max-width

Sẽ có giá trị mặc định là 3 lần fit-content. Nếu bạn cung cấp giá trị, hệ thống sẽ xem xét giá trị được tính toán tối thiểu giữa giá trị mặc định và giá trị bạn cung cấp.

padding-top

Chỉ có hiệu lực nếu bạn đặt height thành auto. Trong trường hợp này, các giá trị lớn hơn 1em sẽ được chỉnh sửa thành 1empadding-bottom sẽ được đặt thành giá trị padding-top.

padding-left

Chỉ có hiệu lực nếu bạn đặt width thành auto. Trong trường hợp này, các giá trị lớn hơn 5em sẽ được chỉnh sửa thành 5empadding-right sẽ được đặt thành giá trị padding-left.

transform

Không được phép sử dụng hiệu ứng hình ảnh làm méo mó. Hiện tại, chúng tôi chỉ chấp nhận dịch 2D và tăng tỷ lệ theo tỷ lệ.

Bạn có thể sử dụng các thuộc tính CSS sau đây như bình thường:

  • font-kerning
  • font-optical-sizing
  • font-stretch
  • font-synthesis-weight
  • font-synthesis-style
  • font-synthesis-small-caps
  • font-feature-settings
  • forced-color-adjust
  • text-rendering
  • align-self
  • anchor-name aspect-ratio
  • border (và tất cả thuộc tính border-*)
  • clear
  • color-scheme
  • contain
  • contain-intrinsic-width
  • contain-intrinsic-height
  • container-name
  • container-type
  • counter-*
  • flex-*
  • float
  • height
  • isolation
  • justify-self
  • left
  • order
  • orphans
  • outline-* (ngoại trừ trường hợp ngoại lệ đã nêu trước đó đối với outline-offset)
  • overflow-anchor
  • overscroll-behavior-*
  • page
  • position
  • position-anchor
  • content-visibility
  • right
  • scroll-margin-*
  • scroll-padding-*
  • text-spacing-trim
  • top
  • visibility
  • x
  • y
  • ruby-position
  • user-select
  • width
  • will-change
  • z-index

Ngoài ra, bạn có thể sử dụng tất cả các thuộc tính tương đương về mặt logic (ví dụ: inline-size tương đương với width), tuân theo các quy tắc tương tự như thuộc tính tương đương.

Lớp giả

Có hai lớp giả đặc biệt cho phép tạo kiểu cho phần tử <permission> dựa trên trạng thái:

  • :granted: Lớp giả lập :granted cho phép tạo kiểu đặc biệt khi được cấp quyền.
  • :invalid: Lớp giả :invalid cho phép tạo kiểu đặc biệt khi phần tử ở trạng thái không hợp lệ, ví dụ: khi phần tử được phân phát trong một iframe nhiều nguồn gốc.
permission {
  background-color: green;
}

permission:granted {
  background-color: light-green;
}

/* Not supported during the origin trial. */
permission:invalid {
  background-color: gray;
}

Sự kiện JavaScript

Phần tử <permission> được dùng cùng với Permissions API. Có một số sự kiện mà bạn có thể theo dõi:

  • onpromptdismiss: Sự kiện này được kích hoạt khi người dùng đóng lời nhắc cấp quyền do phần tử kích hoạt (ví dụ: bằng cách nhấp vào nút đóng hoặc nhấp vào bên ngoài lời nhắc).

  • onpromptaction: Sự kiện này được kích hoạt khi lời nhắc cấp quyền do phần tử kích hoạt đã được người dùng giải quyết bằng cách thực hiện một số hành động trên chính lời nhắc đó. Điều này không nhất thiết có nghĩa là trạng thái quyền đã thay đổi, người dùng có thể đã thực hiện một hành động duy trì hiện trạng (chẳng hạn như tiếp tục cho phép một quyền).

  • onvalidationstatuschange: Sự kiện này được kích hoạt khi phần tử chuyển từ "valid" sang "invalid". Phần tử được coi là "valid" khi trình duyệt tin tưởng tính toàn vẹn của tín hiệu nếu người dùng nhấp vào phần tử đó và "invalid" nếu không, ví dụ: khi phần tử bị nội dung HTML khác che khuất một phần.

Bạn có thể đăng ký trình nghe sự kiện cho các sự kiện này ngay trong dòng mã HTML (<permission type="…" onpromptdismiss="alert('The prompt was dismissed');" />) hoặc sử dụng addEventListener() trên phần tử <permission>, như minh hoạ trong ví dụ sau.

<permission type="camera" />
<script>
  const permission = document.querySelector('permission');
  permission.addEventListener('promptdismiss', showCameraWarning);

  function showCameraWarning() {
    // Show warning that the app isn't fully usable
    // unless the camera permission is granted.
  }

  const permissionStatus = await navigator.permissions.query({name: "camera"});
  
  permissionStatus.addEventListener('change', () => {
    // Run the check when the status changes.
    if (permissionStatus.state === "granted") {
      useCamera();
    }
  });

  // Run the initial check.
  if (permissionStatus.state === "granted") {
    useCamera();
  }
</script>

Phát hiện tính năng

Nếu không hỗ trợ một phần tử HTML, trình duyệt sẽ không hiển thị phần tử đó. Điều này có nghĩa là nếu bạn có phần tử <permission> trong mã HTML, thì sẽ không có gì xảy ra nếu trình duyệt không biết phần tử đó. Bạn vẫn có thể muốn phát hiện khả năng hỗ trợ bằng JavaScript, ví dụ: để tạo lời nhắc cấp quyền được kích hoạt thông qua một lượt nhấp vào <button> thông thường.

if ('HTMLPermissionElement' in window) {
  // The `<permission>` element is supported.
}

Bản dùng thử theo nguyên gốc

Để thử phần tử <permission> trên trang web của bạn với người dùng thực, hãy đăng ký dùng thử phiên bản gốc. Hãy đọc bài viết Bắt đầu dùng thử phiên bản gốc để biết hướng dẫn về cách chuẩn bị trang web của bạn nhằm sử dụng phiên bản gốc. Bản dùng thử theo nguyên gốc sẽ chạy từ Chrome 126 đến 131 (ngày 19 tháng 2 năm 2025).

Bản minh hoạ

Khám phá bản minh hoạ và xem mã nguồn trên GitHub. Dưới đây là ảnh chụp màn hình về trải nghiệm trên một trình duyệt hỗ trợ.

Bản minh hoạ phần tử quyền hiển thị ba nút quyền.

Phản hồi

Chúng tôi rất mong được biết ý kiến của bạn về cách <permission> hoạt động trong trường hợp sử dụng của bạn. Vui lòng phản hồi một trong các Vấn đề trong kho lưu trữ hoặc gửi một vấn đề mới. Các tín hiệu công khai trong repo cho phần tử <permission> sẽ cho chúng tôi và các trình duyệt khác biết rằng bạn quan tâm đến phần tử này.

Câu hỏi thường gặp

  • Cách này tốt hơn <button> thông thường được ghép nối với API quyền như thế nào? Một lượt nhấp vào <button> là một cử chỉ của người dùng, nhưng trình duyệt không có cách nào xác minh rằng lượt nhấp đó có liên kết với yêu cầu cấp quyền hay không. Nếu người dùng đã nhấp vào <permission>, trình duyệt có thể chắc chắn rằng lượt nhấp đó liên quan đến một yêu cầu cấp quyền. Điều này cho phép trình duyệt hỗ trợ các luồng sẽ rủi ro hơn nhiều nếu không có. Ví dụ: cho phép người dùng dễ dàng huỷ chặn một quyền.
  • Điều gì sẽ xảy ra nếu các trình duyệt khác không hỗ trợ phần tử <permission>? Bạn có thể sử dụng phần tử <permission> làm tính năng nâng cao dần dần. Trên các trình duyệt không hỗ trợ, bạn có thể sử dụng luồng cấp quyền kiểu cũ. Ví dụ: dựa trên lượt nhấp vào <button> thông thường. Nhóm quyền cũng đang làm việc trên một polyfill. Đánh dấu kho lưu trữ GitHub để được thông báo khi kho lưu trữ này sẵn sàng.
  • Vấn đề này đã được thảo luận với các nhà cung cấp trình duyệt khác chưa? Thành phần <permission> được thảo luận tích cực tại W3C TPAC năm 2023 trong một phiên họp nhỏ. Bạn có thể đọc ghi chú phiên công khai. Nhóm Chrome cũng đã yêu cầu cả hai nhà cung cấp cung cấp Quan điểm chính thức về tiêu chuẩn, hãy xem phần Đường liên kết liên quan. Phần tử <permission> là chủ đề thảo luận liên tục với các trình duyệt khác và chúng tôi hy vọng có thể chuẩn hoá phần tử này.
  • Đây có thực sự là phần tử rỗng không? Chúng tôi vẫn đang dùng nhiều phương pháp để tranh luận xem <permission> có phải là phần tử rỗng hay không. Nếu bạn có ý kiến phản hồi, hãy tham gia thảo luận về Vấn đề này.

Lời cảm ơn

Tài liệu này đã được Balázs Engedy, Thomas Nguyen, Penelope McLachlan, Marian Harbach, David WarrenRachel Andrew xem xét.