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 trong lần sử dụng đầu tiên thay vì yêu cầu rõ ràng từ 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

Nội dung rác về quyền

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. 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ều này đôi khi được mô tả là nội dung rác về quyền và ảnh hưởng đến cả hai phương pháp, ngầm yêu cầu trong lần sử dụng đầu tiên cũng như yêu cầu rõ ràng ngay từ đầu.

Lời nhắc cấp quyền sử dụng 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ư một lượt 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 đề của phương pháp này là rất khó (nếu không muốn nói là) để trình duyệt tìm hiểu xem liệu một cử chỉ cụ thể của người dùng có dẫn đến lời nhắc cấp quyền xuất hiện hay không. Có thể người dùng chỉ nhấp vào trang một cách khó chịu ở bất cứ đâu vì trang tải quá lâu hoặc có thể họ đã thực sự 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 dễ dàng huỷ

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ở các chế độ kiểm soát trang web của Chrome.

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

Để giải quyết các thách thức được mô tả trong bài đăng này, nhóm phụ trách quyền của Chrome đã phát hành bản dùng thử theo nguyên gốc cho một phần tử HTML mới là <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 tập hợp con 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 sẽ 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, chuỗi phần tử mẹ hoặc một 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 tương tác với phần tử <permission>, người dùng có thể chuyể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 cần được cấp quyền trước, thì văn bản sẽ thay đổi để mời người dùng sử dụng tính năng này. 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 quyền có chứa 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 phải nhu cầu tạo kiểu nào cũng đáp ứng được, nhưng chúng tôi hy vọng sẽ tìm ra những cách an toàn để cho phép tạo kiểu nhiều hơn cho phần tử <permission> sau thời gian dùng thử theo nguyê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 đoạn mã này đều sẽ dẫn đến các trường hợp ngoại lệ có thể phát hiện được bằng JavaScript. Thông báo lỗi sẽ chứa nhiều thông tin chi tiết hơn 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 khoảng giá trị tương đương với smallxxxlarge. Nếu không, thành phần này sẽ bị tắt. Thu phóng sẽ được tính đến khi tính toán font-size.

outline-offset

Giá trị âm sẽ được sửa thành 0.
margin (tất 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ị vượt quá 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ị bạn 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ị tính toán tối đa giữa giá trị mặc định và giá trị đã cung cấp sẽ được xem xét.

max-width

Sẽ có giá trị mặc định là ba lần fit-content. 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ị đã cung cấp sẽ được xem xét.

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 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ả tài sản 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ả :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ể nghe:

  • 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ử đó. Có thể bạn vẫn muốn phát hiện sự hỗ trợ bằng cách sử dụng JavaScript, chẳng hạn như để tạo một lời nhắc cấp quyền được kích hoạt thông qua một lượt nhấp vào một <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 sử dụng bản dùng thử theo nguyên gốc để biết hướng dẫn về cách chuẩn bị trang web của bạn để sử dụng bản dùng thử theo nguyê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 kho lưu trữ 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

  • Tính năng 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? 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 nó được kết nối với yêu cầu xin cấp quyền. Nếu người dùng đã nhấp vào một <permission>, trình duyệt có thể chắc chắn rằng lượt nhấp đó có liên quan đến 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 mà nếu không thì sẽ có nhiều rủi ro hơn. 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 tăng 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ó được thảo luận với nhà cung cấp trình duyệt khác không? 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? Vấn đề này vẫn đang được tích cực tranh luận xem <permission> có nên là một phần tử trố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.