본문 바로가기
source-code/FrontEnd

[chrome extension] 에러 핸들링

by mattew4483 2024. 2. 2.
728x90
반응형

1. No active side panel 에러

chrome.sidePanel.open({ tabId });

sidePanel open api를 호출했을 때 No action side panel 에러가 발생했습니다.

 

await chrome.sidePanel.setOptions({
  tabId,
  path: "sidepanel.html",
  enabled: true,
});

chrome.sidePanel.open({ tabId });

setOptions 후 open을 호출해 해결할 수 있었습니다.

 

2. popup에서 sendMessage를 통한 sidePanel 열기

popup을 클릭했을 때 sendMessage를 호출하고,

background.js에서 해당 message를 수신했을 경우 side panel을 open 하고자 했습니다.

// popup.ts
function onClickPopup() {
  chrome.runtime.sendMessage({
    action: "OPEN_SIDE_PANEL", // side panel open 식별자
  });
}

popup에서 버튼 클릭 시 sendMessage를 호출했고

 

// background.js
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
  const action = message.action;
  console.log(sender.tab?.id, "tab id")
  switch (action) {
    case "OPEN_SIDE_PANEL":
      chrome.sidePanel.setOptions({
        id: sender.tab.id,
        path: "sidepanel.html",
        enabled: true,
      });
      chrome.sidePanel.open({ tabId });
      break;

    default:
      break;
  }
});

background에서 side panel open message 수신 시, open 메서드를 호출했습니다.

 

sender.tab.id가 undefined인 모습!

 

content script에서 호출한 sendMessage의 경우,

onMessage의 addListener의 callback 속 sender 내 tab이 존재하지만 

popup의 경우 sender가 아예 존재하지도 않는 모습입니다.

 

sender의 타입인 MessageSender 인터페이스를 살펴보면

    /**
     * An object containing information about the script context that sent a message or request.
     * @since Chrome 26.
     */
    export interface MessageSender {
        /** The ID of the extension or app that opened the connection, if any. */
        id?: string | undefined;
        /** The tabs.Tab which opened the connection, if any. This property will only be present when the connection was opened from a tab (including content scripts), and only if the receiver is an extension, not an app. */
        tab?: chrome.tabs.Tab | undefined;
        /** The name of the native application that opened the connection, if any.
         * @since Chrome 74
         */
        nativeApplication?: string | undefined;
        /**
         * The frame that opened the connection. 0 for top-level frames, positive for child frames. This will only be set when tab is set.
         * @since Chrome 41.
         */
        frameId?: number | undefined;
        /**
         * The URL of the page or frame that opened the connection. If the sender is in an iframe, it will be iframe's URL not the URL of the page which hosts it.
         * @since Chrome 28.
         */
        url?: string | undefined;
        /**
         * The TLS channel ID of the page or frame that opened the connection, if requested by the extension or app, and if available.
         * @since Chrome 32.
         */
        tlsChannelId?: string | undefined;
        /**
         * The origin of the page or frame that opened the connection. It can vary from the url property (e.g., about:blank) or can be opaque (e.g., sandboxed iframes). This is useful for identifying if the origin can be trusted if we can't immediately tell from the URL.
         * @since Chrome 80.
         */
        origin?: string | undefined;
        /**
         * The lifecycle the document that opened the connection is in at the time the port was created. Note that the lifecycle state of the document may have changed since port creation.
         * @since Chrome 106.
         */
        documentLifecycle?: DocumentLifecycle | undefined;
        /**
         * A UUID of the document that opened the connection.
         * @since Chrome 106.
         */
        documentId?: string | undefined;
    }
 

아하...!

tab의 경우 tab에서 열린 connection이 존재할 경우에만 해당 속성이 존재함을 확인할 수 있었습니다.

(저의 경우 아무런 connection 없이 popup에서 sendMessage 해줬기 때문에, 해당 값이 존재하지 않았던 것!)

 

하지만 sidePanel을 열기 위해서는, 반드시 windowId나 tabId가 존재해야 합니다.

따라서 background에서 side panel 조작 message를 수신했을 경우

현재 열려 있는 탭을 tabId로 전달, 해당 탭 페이지에서 side panel이 뜰 수 있도록 했습니다.

chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
  const action = message.action;
  switch (action) {
    case "OPEN_SIDE_PANEL":
      chrome.tabs.query({ active: true }, function (tabs) {
        const tabId = tabs[0]?.id;
        if (!tabId) console.error("active tab is not exist");
        /** @note setOptions후 open  */
        chrome.sidePanel.setOptions({
          tabId,
          path: "sidepanel.html",
          enabled: true,
        });
        chrome.sidePanel.open({ tabId });
      });
      break;

    default:
      break;
  }
});

tabs.query를 조회해 tabs 중 0번째 id를 tabId로 넘겨줘 해결한 모습!

728x90
반응형