"Bounds must be at least 50% within visible screen space"해결 방법

무슨 잘못이요?


Chrome 102에 추가된 창 구성과 관련된 유효성 검사 오류입니다.
이 예외는 Chrome 확장을 사용하여 창을 만들 때 화면 크기가 너무 크거나 모니터 표시 영역에서 너무 멀리 떨어져 있을 때 발생합니다.
[Extensions] Display window only when its bounds intersect the displays
Windows should only be displayed when they intersect the displays in a
meaningful manner (in this case, window should be visible at least 50%).
Otherwise, the window will be displayed in the current default.
This prevents for windows to be created or moved outside the displays,
and potentially been exploited.
https://source.chromium.org/chromium/chromium/src/+/d51682b36adc22496f45a8111358a8bb30914534
다음 코드로 재현할 수 있습니다.
여기에는 ManifestV3로 기술되어 있지만, ManifestV2도 마찬가지다.
manifest.json
{
  "name": "Open Google",
  "version": "1.0",
  "manifest_version": 3,
  "permissions": [
    "system.display"
  ],
  "background": {
    "service_worker": "background.js"
  },
  "action": {}
}
다음은 화면에 크롬을 표시하는 데 사용되는 코드입니다.
모든 모니터가 대응할 수 있도록 width와 Height에 큰 값을 설정합니다.
background.js
chrome.action.onClicked.addListener(() => {
  chrome.windows.create(
    {
      url: 'https://google.com',
      type: 'popup',
      width: 10000,
      height: 10000,
    },
  )
})
이 Chrome 확장을 시작하면 이런 오류가 발생합니다.
error-message
Uncaught (in promise) Error: Invalid value for bounds. Bounds must be at least 50% within visible screen space.

결론&해결책


디스플레이가 보이지 않는 위치에 놓이지 않도록 추가로 처리한 부산물이다.
다음과 같이 모니터 크기에 따라 창을 만들 수 있습니다.
background.js
chrome.action.onClicked.addListener(() => {
  chrome.system.display.getInfo((display) => {
    // NOTE: 現在表示しているディスプレイサイズを取得
    const { width, height } = display[0].bounds

    chrome.windows.create(
      {
        url: 'https://google.com',
        type: 'popup',
        width,
        height,
      },
    )
  })
})

왜 상술한 방법이 좋을까


잘못된 문장에서 어떻게 위의 방법을 써야 할지 모르기 때문에 잘못된 발생 조건을 읽어 보세요.

잘못된 문장


우선, 잘못된 문장은 여기서 정의한다.
https://source.chromium.org/chromium/chromium/src/+/main:chrome/browser/extensions/api/tabs/tabs_constants.cc;l=111-113?q="Invalid value for bounds"&ss=chromium%2Fchromium%2Fsrc
const char kInvalidWindowBoundsError[] =
    "Invalid value for bounds. Bounds must be at least 50% within visible "
    "screen space.";

오류 발생 조건


상술한 kInvalidWindowBoundsError 호칭의 조건은 여기다.
https://source.chromium.org/chromium/chromium/src/+/main:chrome/browser/extensions/api/tabs/tabs_api.cc;l=919-920;drc=e813b3c6b110bce715d55f4ce12746e2c43aedb9;bpv=0;bpt=1
set_window_bounds는 진짜라고 불리며 W i d ow Bounds Intersect Displays(window bounds)는 가짜다.
if (set_window_bounds && !WindowBoundsIntersectDisplays(window_bounds))
  return RespondNow(Error(tabs_constants::kInvalidWindowBoundsError));

set_window_이른바 bounds


코드를 읽고 창을 만들 때left,top,width,height를 설정하면 진짜가 됩니다.
https://source.chromium.org/chromium/chromium/src/+/main:chrome/browser/extensions/api/tabs/tabs_api.cc;l=901-917;drc=e813b3c6b110bce715d55f4ce12746e2c43aedb9;bpv=0;bpt=1
bool set_window_bounds = false;
if (params->update_info.left) {
  window_bounds.set_x(*params->update_info.left);
  set_window_bounds = true;
}
if (params->update_info.top) {
  window_bounds.set_y(*params->update_info.top);
  set_window_bounds = true;
}
if (params->update_info.width) {
  window_bounds.set_width(*params->update_info.width);
  set_window_bounds = true;
}
if (params->update_info.height) {
  window_bounds.set_height(*params->update_info.height);
  set_window_bounds = true;
}

window_이른바 bounds


Wi n d owBounds IntersectDisplays의 매개변수로 전달되는 창바운스 보러 갈게요.
이것은 창(이후 창으로 약칭)을 만들거나 다시 설정하는 Bounds로 이해할 수 있습니다.
https://source.chromium.org/chromium/chromium/src/+/main:chrome/browser/extensions/api/tabs/tabs_api.cc;l=898-900;drc=e813b3c6b110bce715d55f4ce12746e2c43aedb9;bpv=0;bpt=1
Bounds가 정확한 정의를 찾지 못해서 뭔지 모르겠어요.
코드를 보면 Height,width,left,top 같은 값이 있고, Bounds가 결정하면 창의 면적이 이런 느낌을 받게 됩니다(창의 경계선으로 미리 이해하면 됩니까?).
gfx::Rect window_bounds = browser->window()->IsMinimized()
                            ? browser->window()->GetRestoredBounds()
                            : browser->window()->GetBounds();

이른바 W i n d ow Bounds Intersect Displays


이렇게 정의했습니다.
https://source.chromium.org/chromium/chromium/src/+/main:chrome/browser/extensions/api/tabs/tabs_api.cc;l=432-440;drc=e813b3c6b110bce715d55f4ce12746e2c43aedb9?q=kInvalidWindowBoundsError&ss=chromium%2Fchromium%2Fsrc
intersect_area를 합친 후 창 면적과 비교하고 진짜와 가짜를 되돌려줍니다.
bool WindowBoundsIntersectDisplays(const gfx::Rect& bounds) {
  int intersect_area = 0;
  for (const auto& display : display::Screen::GetScreen()->GetAllDisplays()) {
    gfx::Rect display_bounds = display.bounds();
    display_bounds.Intersect(bounds);
    intersect_area += display_bounds.size().GetArea();
  }
  return intersect_area >= (bounds.size().GetArea() / 2);
}
다시 자세히 볼게요.
우선 여기에서 모든 모니터에 대해 bounds를 얻었습니다.
for (const auto& display : display::Screen::GetScreen()->GetAllDisplays()) {
  gfx::Rect display_bounds = display.bounds();
  ...
이후 창의 Intersect를 가져와 치수를 합산합니다.
  ...
  display_bounds.Intersect(bounds);
  intersect_area += display_bounds.size().GetArea();
}
Intersect 방법은 여기서 정의됩니다.
https://source.chromium.org/chromium/chromium/src/+/main:ui/gfx/geometry/rect.cc;l=162-179;drc=e813b3c6b110bce715d55f4ce12746e2c43aedb9;bpv=0;bpt=0
코드를 보니 모니터와 창이 겹치는 곳을 얻은 것 같다.
분위기지만 그런 인상입니다.
창 크기 > 창 크기, 창 크기,intersect -area 일치
intersect_example
<창 크기를 표시할 때 치수 및 intersect>area 일치
intersect_example2
그리고 디스플레이와 창이 겹치지 않을 때intersectarea가 0이 됩니다.
void Rect::Intersect(const Rect& rect) {
  if (IsEmpty() || rect.IsEmpty()) {
    SetRect(0, 0, 0, 0);  // Throws away empty position.
    return;
  }

  int left = std::max(x(), rect.x());
  int top = std::max(y(), rect.y());
  int new_right = std::min(right(), rect.right());
  int new_bottom = std::min(bottom(), rect.bottom());

  if (left >= new_right || top >= new_bottom) {
    SetRect(0, 0, 0, 0);  // Throws away empty position.
    return;
  }

  SetByBounds(left, top, new_right, new_bottom);
}

intersect_area >= (bounds.size().GetArea() / 2)


이것은 모니터와 창이 겹치는 영역의 병합과 창 크기를 비교하는 곳이다.
여기, 2를 나눈 곳은 Bounds must be at least 50% within visible screen space의 50%에 해당한다.
좀 복잡해서 코드를 읽을 수 없지만 창의 크기는 정확하게 사용할 수 있는 창의 크기를 가리키는 것 같습니다.
Mac의 경우 "Mac 정보"모니터를 통해 디스플레이 크기를 얻을 수 있습니다.
아래의 위치는width=>1920px,height=>1080px입니다.
window-size
이 가격과 바운드.size().GetArea()의 치수가 올바르면 아래도 이동해야 합니다.
그러나 발생했다Bounds must be at least 50%....
background.js
...
    const { width, height } = display[0].bounds

    chrome.windows.create(
      {
        url: 'https://google.com',
        type: 'popup',
        width,
        height: height * 2,
      },
    )
...
정확히 창문입니다.screen이 얻을 수 있는 avil Width, avil Height의 값입니다.
(참고로 Chrome Extension ManifestV3은 서비스 워커에서 실행되며 window 함수에 접근할 수 없고 시작할 때 이 값을 설정할 수 없습니다.)
screen-width
내 환경에서height: 1055 * 2는 일하는 것이고height: 1055 * 2 + 1는 잘못된 것이다.
background.js
    chrome.windows.create(
      {
        url: 'https://google.com',
        type: 'popup',
        width,
        height: 1055 * 2,
      },
    )

총결산


Chrome 102에서 창 구성에 대한 프롬프트가 추가되어 모니터와 창의 간격이 크거나 창이 너무 크면 오류가 표시됩니다.
크롬 코드를 보면 어떤 조건에서 발생했는지, 왜 추가됐는지 알 수 있고, 어려우면 크롬 코드를 읽어보세요!

참고 자료


https://github.com/pilefort/new-chrome-window-validate-from-chrome102
이상

좋은 웹페이지 즐겨찾기