精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

都 2021 年了,做個 Chrome 插件給自己吧!

系統 Linux
我希望能夠開發一個 Chrome 瀏覽器插件,當前其他瀏覽器如 Edge、Firefox、Brave,以及其他所有使用 Chromimum 開發的瀏覽器都是支持 Chrome 插件格式的,而這幾大瀏覽器幾乎占據了近 83% 左右的桌面端瀏覽器市場,所以這個 Chrome 插件可以在我喜歡的瀏覽器上運行。

[[439663]]

本文轉載自微信公眾號「程序員巴士」,作者一只圖雀  。轉載本文請聯系程序員巴士公眾號。

大家好,我是皮湯。

隨著入職時間變長,工作不斷的深入,在需要同時處理多個任務的同時,打開幾十上百個瀏覽器 Tab 頁就必不可少了,而我的工作幾乎都是在各種瀏覽器 Tab 頁之間來回切換,如寫文檔、學習新知識、處理 Bug 單流轉、上線等流程,所以我需要對瀏覽器的 Tab 頁進行精細化管理,以達到精細化管理工作流程的目的,于是乎,我對于瀏覽器的使用變成了下面幾個階段:

Chrome - 雜亂無章階段

Chrome - 進行適當整理

Edge - 豎向側邊欄

但是無論瀏覽器層面提供多少這樣或那樣的輔助,但畢竟瀏覽器的職責主要是負責幫助你更好、更快、更高效的瀏覽網頁,并非是幫你管理知識和工作流程,所以如果需要個性化定制的需求,就得自己上手開發啦!畢竟作為程序員,自己動手,豐衣足食嘛 ??。

需求分析

我希望能夠開發一個 Chrome 瀏覽器插件,當前其他瀏覽器如 Edge、Firefox、Brave,以及其他所有使用 Chromimum 開發的瀏覽器都是支持 Chrome 插件格式的,而這幾大瀏覽器幾乎占據了近 83% 左右的桌面端瀏覽器市場,所以這個 Chrome 插件可以在我喜歡的瀏覽器上運行。

以下是 2020.3 到 2021.3 的桌面端瀏覽器占比數據

這個瀏覽器支持傳統的插件點擊彈出欄,以及每次打開一個新 Tab 都能展示我的應用,這樣能夠幫助我隨時了解我當前正在進行的工作,大致形式如下:

彈出欄:

新 Tab:

針對上面需求的形式不知道大家是否比較熟悉了?沒錯,這個插件的框架形式和 掘金 的插件類似,我們看下掘金的 Chrome 插件:

彈出框:

新 Tab:

也就是說,在看完本次文章,你基本上擁有了開發一個掘金插件的能力,心動了???

隨便一提,我們本次開發插件的技術棧如下:

  • React + TypeScript,基于 Create-React-App 腳手架搭建

通過先進的技術棧來編寫 Chrome 插件??。

前置知識

Chrome 插件實際上包含幾個部分:

  • manifest.json 文件,相當于整個項目的入口,里面記錄著此插件的 icon 圖標展示、彈出框樣式文件、新建 Tab 邏輯、選項邏輯、內容腳本邏輯等
  • background.js,此腳本是在整個瀏覽器啟動或者插件加載之后就會運行的一個腳本文件,它運行在 ServiceWorker 里面,通常用于進行一些前置的數據 storage 存儲操作,可以操作所有的 Chrome API
  • popup.html,插件的彈出框展示的模板內容,可以通過 CSS 控制樣式,JavaScript 控制邏輯
  • options.html,右鍵插件 icon 時彈出菜單頁,點擊菜單頁里面的選項打開的頁面
  • content.js,此腳本是在你打開一個新的網頁的時候,Chrome 瀏覽器為這個網頁注入的一個腳本文件,用于輔助此網頁和你的插件進行一個通信,因為插件的運行環境是經過沙盒隔離的,無法直接操作到 DOM,所以需要通過 content 腳本操作 DOM,然后發送給到插件的處理邏輯

上述 5 大文件組成了一個 Chrome 插件所需要的必須元素,邏輯關系如下:

可以看到,其實開發一個 Chrome 的插件也是使用 HTML/JavaScript/CSS 這些知識,只不過使用場景,每種 JavaScript 使用的權限與功能、操作的 API 不太一樣,那么既然是使用基本的 Web 基礎技術,我們就可以借助更為上層的 Web 開發框架如 React 等來將 Chrome 插件的開發上升到一個現代化的程度。

最簡化插件

確保你安裝了最新版的 Node.js,然后在命令行中運行如下命令:

  1. npx create-react-app chrome-react-extension --template typescript 

初始化好項目、安裝完依賴之后,我們可以看到 CRA 產生的模板代碼,其中就有我們需要的 public/manifest.json 文件:

當然內容并沒有我們上圖那樣豐富我們需要做一些修改,將內容改為如下內容:

  1.    "name""Chrome React Extension"
  2.    "description""使用 React TypeScript 構建 Chrome 擴展"
  3.    "version""1.0"
  4.    "manifest_version": 3, 
  5.    "action": { 
  6.        "default_popup""index.html"
  7.        "default_title""Open the popup" 
  8.    }, 
  9.    "icons": { 
  10.        "16""logo192.png"
  11.        "48""logo192.png"
  12.        "128""logo192.png" 
  13.    } 

上述的字段說明如下:

  • name:插件的名字,展示在 Chrome 插件 icon 里面,以及插件市場等
  • description:簡介插件時干嘛的
  • version:插件當前的版本
  • manifest_version:當前使用的 manifest 文件的版本,Chrome 插件最小的 manifest 版本是 V3
  • action:控制點擊插件 icon 時的需要反應的動作(action),這里我們設置 hover 時展示的文字為 default_title,點擊打開展示的內容為 index.html
  • icons:為展示在 Chrome 插件里面的圖標

實際上 Chrome 插件只能理解原生的 JavaScript,CSS,HTML 等, 所以我們使用 React 學完之后,需要進行構建,將構建的產物打包給到瀏覽器插件去加載使用,在構建時,還有一個需要注意的就是,為了保證最優化性能,CRA 的腳本在構建時會將一些小的 JS 文件等,內聯到 HTML 文件中,而不是打包成獨立的 JS 文件,在 Chrome 插件的運行環境下,這種形式的 HTML 是不支持的,會觸發插件的 CSP(內容安全策略)錯誤。

所以為了測試我們的插件當前效果,我們修改構建腳本,在 package.json 里面:

  1. "scripts": { 
  2.     "start""react-scripts start"
  3.     "build""INLINE_RUNTIME_CHUNK=false react-scripts build"
  4.     "test""react-scripts test"
  5.     "eject""react-scripts eject" 
  6.   }, 

通過設置 INLINE_RUNTIME_CHUNK=false 確保所有的 JS 會構建成獨立的文件,然后引入到 HTML 中加載使用。

一切準備完畢,是時候構建我們的 React 應用了~ 在命令行中運行如下命令:

  1. npm run build 

會發現內容構建輸出在 build/xxx 下面,包含 manifest.json、index.html、對應的 JS/CSS 文件還有圖片等,其中 manifest 中索引了 index.html 來作為點擊插件時的 Popup 的展示頁,這個時候我們就可以使用 Chrome 加載我們構建好的文件,來查看插件運行效果了:

我們打開擴展程序面板,設置開發者模式,然后點擊加載文件,選擇我們的 build 文件地址加載:

Magic !我們可以在瀏覽器里面看到我們的插件,并使用它了,一個最簡化插件完成!??

當然這里我們雖然能夠使用 React/TypeScript 以及一切現代的 Web 開發技術來寫插件,但是目前沒有很好的方式能夠實時的進行開發-查看效果,就是我們常見的 HMR、Live Reload 這種技術暫時還沒有很好的支持到 Chrome 插件的開發,所以每次我們需要查看編寫的效果都需要構建之后點擊插件查看。

當然如果純針對 UI 或者和 Chrome API 無關的邏輯,那么你可以放心的直接在 Web 里面開發,等到開發完畢再構建到 Chrome 插件預覽即可。

定制新 Tab 邏輯

我們之前的邏輯是,只要新開一個 Tab,那么就會訪問我們提供的頁面,類似掘金的插件,而且我們也主要到,其實針對 Popup 頁面只是幾個按鈕,而重頭戲都在新 Tab 頁界面展示,也就是我們這里其實需要一個多頁應用?因為最終要生成頁面,一個用在 Popup 頁面展示,一個用在新 Tab 頁展示。

但是我們知道 CRA 腳手架生成的模板是主要用于單頁應用,如果需要切換到多頁應用有一定的成本,但是我們的 Popup 頁面實際上就只有幾個按鈕,所以這里可以做一層簡化,即 Popup 頁面直接手動寫最原始的 HTML/JS/CSS,然后將重頭戲、復雜的新 Tab 頁的邏輯來用 React TypeScript 等現代 Web 技術來開發。

通過這樣設計之后,我們的目錄結構變成了如下形式:

其中 manifest.json 的邏輯變成了如下:

  1.   "name""Chrome React SEO Extension"
  2.   "description""The power of React and TypeScript for building interactive Chrome extensions"
  3.   "version""1.0"
  4.   "manifest_version": 3, 
  5.   "action": { 
  6.     "default_popup""./popup/index.html"
  7.     "default_title""Open the popup" 
  8.   }, 
  9.   "chrome_url_overrides": { 
  10.     "newtab""index.html" 
  11.   }, 
  12.   "icons": { 
  13.     "16""logo192.png"
  14.     "48""logo192.png"
  15.     "128""logo192.png" 
  16.   } 

我們可以看到,點擊 Chrome 插件彈出的頁面 Popup,換成了 ./popup/index.html ,而我們新加了一個 chrome_url_overrides 字段,在 newtab 時,我們打開構建后的 index.html 文件。

通過上面的操作,我們每次打開一個新 Tab,都會展示下面的頁面:

完美!我們已經實現了掘金的插件的核心思想:便捷的獲取技術知識,就在你每次打開 Tab 時。

開發 Popup 頁面

接下來我們嘗試改造一下我們的 Popup 頁面,同樣是對標掘金,我們知道掘金的 Popup 頁面是一個比較簡單的菜單欄,里面主要是一些用于跳轉到新 Tab 或者設置頁的操作:

我們現在也需要實現類似的點擊某個按鈕,跳轉到我們新 Tab 頁,打開我們上一部分定制的 Tab 邏輯。

這一部分我們就需要修改 popup/index.html ,添加相關的 JS 邏輯如下:

 

 

 

 

 

 

  1. <!DOCTYPE html> 
  2. <html lang="en"
  3.   <head> 
  4.     <meta charset="UTF-8" /> 
  5.     <meta http-equiv="X-UA-Compatible" content="IE=edge" /> 
  6.     <meta name="viewport" content="width=device-width, initial-scale=1.0" /> 
  7.     <title>Fake Juejin Extensions</title> 
  8.     <link rel="stylesheet" href="./styles.css" /> 
  9.   </head> 
  10.   <body> 
  11.     <ul> 
  12.       <li class="open_new_tab">打開新標簽頁</li> 
  13.       <li class="go_to_github">訪問 Github</li> 
  14.       <li class="go_to_settings">設置</li> 
  15.     </ul> 
  16.     <script src="popup.js"></script> 
  17.   </body> 
  18. </html> 

 

 

 

 

這一次需求我們只會操作打開新標簽頁、訪問 Github,設置我們不做操作,留給讀者自己去擴展。

可以看到我們導入了 popup.js 文件,在這個 JS 文件里,我們需要完成對應打開新標簽頁、和訪問 Github 的邏輯配置:

  1. document.querySelector(".open_new_tab").addEventListener("click", (e) => { 
  2.   chrome.tabs.create({}, () => {}); 
  3. }); 
  4.  
  5. document.querySelector(".go_to_github").addEventListener("click", (e) => { 
  6.   window.open("https://github.com"); 
  7. }); 

可以看到,因為 popup.js 是運行在 Chrome 插件的沙箱環境下的,所以它能夠使用到 chrome 這個 API,進行頁面、瀏覽器等相關的操作。

當我們寫入了上述邏輯之后,我們就可以點擊對應的打開新標簽頁,訪問新標簽頁并展示我們上一節說到的內容,訪問 Github,則會跳轉到 Github 頁面。

使用 Content 腳本

我們已經開發了新 Tab 頁,開發了 Popup 邏輯,接下來我們可以嘗試一下通過 content 腳本,來實現用戶頁面與插件腳本進行通信,以間接的操作 DOM。

首先我們需要在 manifest.json 里面注冊 content 相關的腳本:

  1.   "name""Chrome React Extension"
  2.   // ... 
  3.   "permissions": ["activeTab""tabs"], 
  4.   "content_scripts": [ 
  5.     { 
  6.       "matches": ["http://*/*""https://*/*"], 
  7.       "js": ["./static/js/content.js"
  8.     } 
  9.   ] 

上述腳本通過 content_scripts 指定 content 腳本,matches 指定匹配到那些域名時,才執行這個注入腳本的邏輯,js 代表需要注入的腳本的位置,這里我們填寫的為 ./static/js/content.js ,即為通過構建之后產生的 JS 內容地址。

接著我們在 Tab 頁的 React 項目里面去建立與 content 腳本的通信:

  1. import React from "react"
  2. import "./App.css"
  3. import { DOMMessage, DOMMessageResponse } from "./types"
  4.  
  5. function App() { 
  6.   // 前置邏輯 
  7.  
  8.   React.useEffect(() => { 
  9.     /** 
  10.      * We can't use "chrome.runtime.sendMessage" for sending messages from React. 
  11.      * For sending messages from React we need to specify which tab to send it to. */     chrome.tabs && 
  12.       chrome.tabs.query( 
  13.         { 
  14.           active: true
  15.           currentWindow: true
  16.         }, 
  17.         (tabs) => { 
  18.           /** 
  19.            * Sends a single message to the content script(s) in the specified tab, 
  20.            * with an optional callback to run when a response is sent back. 
  21.            * 
  22.            * The runtime.onMessage event is fired in each content script running 
  23.            * in the specified tab for the current extension. */           chrome.tabs.sendMessage( 
  24.             tabs[0].id || 0, 
  25.             { type: "GET_DOM" } as DOMMessage, 
  26.             (response: DOMMessageResponse) => { 
  27.               setTitle(response.title); 
  28.               setHeadlines(response.headlines); 
  29.             } 
  30.           ); 
  31.         } 
  32.       ); 
  33.   }); 
  34.  
  35.   return ( 
  36.     // ... 模板 
  37.   ); 
  38.  
  39. export default App; 

可以看到我們通過 chome API,去查詢當前正在激活的 Tab 頁,然后給這個 Tab 頁的 content 腳本,通過 chrome.tabs.sendMessage 發了一個 { type: "GET_DOM" } 的消息。

然后我們創建對應的 content 的腳本,在 src/chromeServices 下創建 DOMEvaluator.ts:

  1. import { DOMMessage, DOMMessageResponse } from "../types"
  2.  
  3. // Function called when a new message is received const messagesFromReactAppListener = ( 
  4.   msg: DOMMessage, 
  5.   sender: chrome.runtime.MessageSender, 
  6.   sendResponse: (response: DOMMessageResponse) => void 
  7. ) => { 
  8.   console.log("[content.js]. Message received", msg); 
  9.  
  10.   const headlines = Array.from(document.getElementsByTagName<"h1">("h1")).map( 
  11.     (h1) => h1.innerText 
  12.   ); 
  13.  
  14.   // Prepare the response object with information about the site   const response: DOMMessageResponse = { 
  15.     title: document.title, 
  16.     headlines, 
  17.   }; 
  18.  
  19.   sendResponse(response); 
  20. }; 
  21.  
  22. /** 
  23.  * Fired when a message is sent from either an extension process or a content script. */ chrome.runtime.onMessage.addListener(messagesFromReactAppListener); 

這個腳本在加載的時候,通過 onMessage.addListener 監聽,然后回調 messagesFromReactAppListener ,在函數里面,可以直接獲取 DOM,查詢這個頁面中的 標題 和所有的 H1 標簽,然后返回。

  1. import React from "react"
  2. import "./App.css"
  3. import { DOMMessage, DOMMessageResponse } from "./types"
  4.  
  5. function App() { 
  6.   const [title, setTitle] = React.useState(""); 
  7.   const [headlines, setHeadlines] = React.useState<string[]>([]); 
  8.  
  9.   // ...消息通信邏輯 
  10.  
  11.   return ( 
  12.     // ... 模板 
  13.     <div className="App"
  14.       <h1>SEO Extension built with React!</h1> 
  15.  
  16.       <ul className="SEOForm"
  17.         <li className="SEOValidation"
  18.           <div className="SEOValidationField"
  19.             <span className="SEOValidationFieldTitle">Title</span> 
  20.             <span 
  21.               className={`SEOValidationFieldStatus ${ 
  22.                 title.length < 30 || title.length > 65 ? "Error" : "Ok" 
  23.               }`} 
  24.             > 
  25.               {title.length} Characters 
  26.             </span> 
  27.           </div> 
  28.           <div className="SEOVAlidationFieldValue">{title}</div> 
  29.         </li> 
  30.  
  31.         <li className="SEOValidation"
  32.           <div className="SEOValidationField"
  33.             <span className="SEOValidationFieldTitle">Main Heading</span> 
  34.             <span 
  35.               className={`SEOValidationFieldStatus ${ 
  36.                 headlines.length !== 1 ? "Error" : "Ok" 
  37.               }`} 
  38.             > 
  39.               {headlines.length} 
  40.             </span> 
  41.           </div> 
  42.           <div className="SEOVAlidationFieldValue"
  43.             <ul> 
  44.               {headlines.map((headline, index) => ( 
  45.                 <li key={index}>{headline}</li> 
  46.               ))} 
  47.             </ul> 
  48.           </div> 
  49.         </li> 
  50.       </ul> 
  51.     </div> 
  52.   ); 
  53.  
  54. export default App; 

然后擴展一下 CSS 代碼:

  1. .App { 
  2.   background: #edf0f6; 
  3.   padding: 0.5rem; 
  4.  
  5. .SEOForm { 
  6.   list-style: none; 
  7.   margin: 0; 
  8.   box-shadow: 0 1px 3px 0 rgb(0 0 0 / 10%), 0 1px 2px 0 rgb(0 0 0 / 6%); 
  9.   background: #fff; 
  10.   padding: 1rem; 
  11.  
  12. .SEOValidation { 
  13.   margin-bottom: 1.5rem; 
  14.  
  15. .SEOValidationField { 
  16.   width: 100%; 
  17.   display: flex; 
  18.   justify-content: space-between
  19.  
  20. .SEOValidationFieldTitle { 
  21.   font-size: 1rem; 
  22.   color: #1a202c; 
  23.   font-weight: bold; 
  24.  
  25. .SEOValidationFieldStatus { 
  26.   color: #fff; 
  27.   padding: 0 1rem; 
  28.   height: 1.5rem; 
  29.   font-weight: bold; 
  30.   align-items: center; 
  31.   display: flex; 
  32.   border-radius: 9999px; 
  33.  
  34. .SEOValidationFieldStatus.Error { 
  35.   background-color: #f23b3b; 
  36.  
  37. .SEOValidationFieldStatus.Ok { 
  38.   background-color: #48d660; 
  39.  
  40. .SEOVAlidationFieldValue { 
  41.   overflow-wrap: break-word; 
  42.   width: 100%; 
  43.   font-size: 1rem; 
  44.   margin-top: 0.5rem; 
  45.   color: #4a5568; 

Nice!我們成功編寫了新 Tab 頁模板、邏輯與樣式,以及創建了 Content 腳本邏輯,最后我們的展示效果如下:

然后我們需要進行代碼構建,因為 content 我們使用 TypeScript 語法寫,將 content 的邏輯構建為單獨的 JS 輸出,我們安裝 craco 依賴,然后修改對應的腳本:

  1. yarn add -D craco 
  2. // package.json 
  3. "scripts": { 
  4.     "start""react-scripts start"
  5.     "build""INLINE_RUNTIME_CHUNK=false craco build"
  6.     "test""react-scripts test"
  7.     "eject""react-scripts eject" 
  8.   }, 

將 react-scripts 改為 craco 。

然后新建 craco.config.js ,添加如下內容:

  1. module.exports = { 
  2.   webpack: { 
  3.     configure: (webpackConfig, { env, paths }) => { 
  4.       return { 
  5.         ...webpackConfig, 
  6.         entry: { 
  7.           main: [ 
  8.             env === "development" && 
  9.               require.resolve("react-dev-utils/webpackHotDevClient"), 
  10.             paths.appIndexJs, 
  11.           ].filter(Boolean), 
  12.           content: "./src/chromeServices/DOMEvaluator.ts"
  13.         }, 
  14.         output: { 
  15.           ...webpackConfig.output
  16.           filename: "static/js/[name].js"
  17.         }, 
  18.         optimization: { 
  19.           ...webpackConfig.optimization, 
  20.           runtimeChunk: false
  21.         }, 
  22.       }; 
  23.     }, 
  24.   }, 
  25. }; 

準備完畢,開始構建:yarn`` build ,我們會發現構建目錄輸出如下:

寫在最后

在本篇文章中,我們完整體驗了使用 React+TypeScript,開發新 Tab 內容展示頁以及 content 通信腳本,然后通過配置 react-scripts 為 craco 進行了分文件構建,以及直接開發原生的 popup 頁,通過這種融匯的技術,成功開發出了一個類似掘金框架的 Chrome 插件。

 

這篇文章沒有介紹的有 background 腳本,以及整體插件內容還不夠完善,希望有興趣的讀者可以繼續探索,將其完善。

 

責任編輯:武曉燕 來源: 程序員巴士
相關推薦

2010-03-25 16:08:19

2021-06-10 10:33:22

Jenkins持續集成工具自動化

2021-12-14 08:26:52

Chrome瀏覽器Google

2021-03-16 22:44:18

Go語言開發

2021-01-11 08:31:15

TypeScript開源項目

2011-02-18 13:31:22

Web 設計和開發 C

2013-02-27 11:04:39

ClouderaRocketFuel大數據

2022-04-18 19:02:53

chrome擴展瀏覽器

2021-01-21 17:49:20

計算機軟件病毒

2021-10-28 15:36:08

架構運維技術

2010-03-26 14:22:03

Chrome瀏覽器

2018-05-05 14:18:22

蘋果MacWindows

2022-06-08 10:32:49

FlutterChrome前端

2020-12-17 08:02:42

MyBatis插件框架

2021-07-26 05:49:17

jQuery開發

2015-07-16 10:34:01

SafariFirefox chrome

2015-07-15 17:43:06

Flash瀏覽器

2021-01-15 18:37:25

微軟WindowsWindows 10

2021-12-10 07:47:30

谷歌開發者工具

2021-12-09 09:15:34

GoogleChrome擴展程序
點贊
收藏

51CTO技術棧公眾號

青青草原综合久久大伊人精品 | www.久久| 麻豆成人av在线| 亚洲国产精品专区久久| 国产成人aa精品一区在线播放| 久久成年人网站| 日韩精品久久久久久免费| 国产电影一区| 国产精品美女久久久久高潮| 亚洲91精品在线观看| 下面一进一出好爽视频| 岛国最新视频免费在线观看| 精品福利网址导航| 亚洲人精品午夜| 国产美女久久精品| 91成人在线免费视频| 国产v日韩v欧美v| 国产美女久久久久| 视频在线观看99| 成人精品小视频| 日产精品久久久久久久性色| 国内精品久久久久久久97牛牛 | 一区二区美女视频| 国产一区二区三区电影在线观看| 午夜精品久久久久影视| 91美女高潮出水| 国产麻豆a毛片| av在线不卡精品| 中文无字幕一区二区三区| 国产91色在线免费| 欧美偷拍一区二区三区| 伊人精品久久| 亚洲第一在线综合网站| 国内一区在线| 麻豆久久久久久久久久| 日韩欧美在线精品| 欧美日韩美女在线| 欧美亚洲一级二级| 国产在线视频你懂的| 精品欧美视频| 一区二区三区中文字幕精品精品 | 国产黄页在线观看| 日韩一级片免费| 99在线观看免费视频精品观看| 精品捆绑美女sm三区| 国产素人在线观看| 国外av在线| 麻豆久久一区二区| 日韩av日韩在线观看| 在线观看 中文字幕| 色棕色天天综合网| 欧美日本国产视频| 欧美做受777cos| 十八禁一区二区三区| 水蜜桃久久夜色精品一区的特点| 在线精品视频视频中文字幕| 热久久久久久久久| 日韩av电影资源网| 欧美亚洲综合另类| 在线观看av的网址| 超鹏97在线| 成人高清免费观看| 国产999在线观看| 久久久成人免费视频| 久久人人超碰| 国产精品久久久久免费a∨大胸| 农村妇女精品一区二区| 日本久久成人网| 欧美日韩一本到| 成人免费毛片在线观看| www.亚洲.com| 成人毛片老司机大片| 国产精品美女久久| 亚洲在线视频播放| 一区二区动漫| 日本不卡视频在线播放| 成人在线观看小视频| 久久93精品国产91久久综合| 亚洲欧美一区二区三区久久| 日本黄色三级网站| 91欧美极品| 欧美日韩成人一区二区| 一二三级黄色片| 国产精品18hdxxxⅹ在线| 欧美日韩亚州综合| 国产福利精品一区二区三区| 99久久人爽人人添人人澡 | 欧美精品久久久久久久久久丰满| 久久国产夜色精品鲁鲁99| 成人精品aaaa网站| 无码人妻精品一区二区三区蜜桃91| 欧美一区视频| 中文字幕日韩专区| 免费看污黄网站在线观看| 日韩中文字幕| 91麻豆精品国产91久久久资源速度 | www免费网站在线观看| 亚洲欧美国产高清| 亚洲一区二区在线免费观看| 青青草娱乐在线| 国产精品人人做人人爽人人添| 51xx午夜影福利| 向日葵视频成人app网址| 婷婷中文字幕综合| 黄色成人在线看| 日本美女久久| 亚洲第一福利网| 国产视频精品视频| 88久久精品| 国产亚洲精品va在线观看| 日韩精品卡通动漫网站| 亚洲啊v在线观看| 日韩视频第一页| 日韩在线一卡二卡| 国产亚洲一区在线| 日韩av电影手机在线| 99草在线视频| 国产精品乡下勾搭老头1| 91精品国产自产在线老师啪 | 777午夜精品免费视频| 亚洲成人福利视频| 91国内精品白嫩初高生| 在线看日韩欧美| 天天操天天摸天天干| 国产不卡在线一区| 国外成人在线视频网站| 午夜久久久久久噜噜噜噜| 国产在线精品免费av| 欧美午夜欧美| 在线女人免费视频| 欧美亚洲精品一区| 国产亚洲色婷婷久久99精品91| 亚洲大片精品免费| 亚洲性生活视频在线观看| 国产无遮挡aaa片爽爽| 国产真实乱子伦精品视频| 婷婷久久青草热一区二区| 黄色片网站在线| 夜夜嗨av一区二区三区网页 | 亚洲综合不卡| 国产精品白嫩初高中害羞小美女 | 日本亚洲三级在线| 国产深夜精品福利| 国产二区视频在线观看| 福利视频第一区| 亚洲观看黄色网| 国产精品永久| 免费成人深夜夜行视频| av大片在线播放| 亚洲精品中文在线观看| 亚洲一二三不卡| 欧美18xxxx| 69久久夜色精品国产7777| 丰满熟女人妻一区二区三| 国产又黄又大久久| 2021狠狠干| 成人影院入口| 91精品国产综合久久精品性色| 丰满人妻一区二区三区免费视频棣| 天堂资源在线亚洲| 26uuu亚洲伊人春色| 999国产精品视频免费| 亚洲欧美成人一区二区三区| 中文字幕一区二区在线观看视频| 亚洲精品va| 成人永久免费| 91社区在线| 7777精品久久久大香线蕉 | 91精品高清| 亚洲精品免费网站| 国产色在线 com| 色婷婷激情综合| 亚洲 自拍 另类 欧美 丝袜| 欧美日韩三区| 91精品久久久久久久久久入口| 天天综合视频在线观看| 欧美日韩一区二区免费在线观看| 我和岳m愉情xxxⅹ视频| 美女mm1313爽爽久久久蜜臀| 日本美女爱爱视频| 神马久久av| 国产精选久久久久久| 五月婷婷视频在线观看| 欧美揉bbbbb揉bbbbb| 日韩精品一区二区三区在线视频| 国产精品一区二区久激情瑜伽| www..com日韩| av亚洲在线观看| 欧美最猛黑人xxxx黑人猛叫黄| 黄色美女网站在线观看| 制服丝袜亚洲精品中文字幕| 国产无精乱码一区二区三区| 欧美国产一区二区| 韩国一区二区av| 私拍精品福利视频在线一区| 国产精品视频xxx| 丁香花电影在线观看完整版| 日韩欧美一区在线| 国产精品国产精品88| 97精品国产97久久久久久久久久久久| 97超碰人人爱| 夜夜躁狠狠躁日日躁2021日韩| 91精品视频在线播放| 中文字幕乱码中文乱码51精品| www亚洲欧美| 欧美孕妇性xxxⅹ精品hd| 日韩一区二区中文字幕| 69xx绿帽三人行| 国产一区二区三区在线观看精品| 日韩av中文字幕第一页| 欧美激情黄色片| 91免费视频网站| 欧美大片免费观看网址| 亚洲午夜激情免费视频| 亚洲精品免费在线观看视频| 亚洲福中文字幕伊人影院| 国产精品理论在线| 精品无人码麻豆乱码1区2区| 中文字幕在线观看一区二区三区| 亚洲精品大全| 另类视频在线观看| 午夜精品久久久久久久99老熟妇| 在线观看视频一区二区欧美日韩| 国产伦理片在线观看| 美女视频一区在线观看| 国产精品亚洲天堂| 97人人澡人人爽91综合色| 国产精品美女午夜av| 国模冰冰炮一区二区| 国内自拍欧美激情| 国产精品99999| 亚洲精品久久久久| 好吊视频一区二区三区| 精品欧美国产一区二区三区| 国产稀缺精品盗摄盗拍| 国产精品毛片大码女人| 91激情视频在线观看| 久久久另类综合| 久热在线视频观看| 亚洲性人人天天夜夜摸| 欧美亚州在线观看| 亚洲日产av中文字幕| 久久久久久高清| 亚洲mmav| 国产成人精品优优av| 亚洲淫成人影院| 5566日本婷婷色中文字幕97| 日韩欧美一中文字暮专区| 色吧影院999| 不卡在线视频| 深夜福利91大全| 欧美三级黄网| 日韩成人中文字幕| 亚洲av综合一区| 91成人看片片| 国产偷人爽久久久久久老妇app| 欧洲视频一区二区| 亚洲视频在线观看一区二区 | 国产精品污视频| 午夜精品久久久| 国产午夜福利片| 欧美日韩在线免费| 波多野结衣理论片| 五月天国产精品| 亚洲精品午夜国产va久久成人| 色综合久久中文字幕| 中文字幕欧美色图| 黑丝美女久久久| 国产主播第一页| 欧美喷潮久久久xxxxx| 日韩欧美性视频| 欧美日韩视频在线| 精品国产www| 欧美一卡二卡三卡| 污污视频在线免费看| 日韩午夜av一区| 色婷婷av一区二区三| 亚洲天堂男人的天堂| 国产精品久久麻豆| 91精品国产99| 亚洲爽爆av| 国产精品中文久久久久久久| 9999精品| 精品一区久久久| 97视频精品| 免费看黄在线看| 蜜臀va亚洲va欧美va天堂| 女人高潮一级片| 9色porny自拍视频一区二区| 欧美老女人bb| 国产午夜精品福利| 国产精品高清无码在线观看| 国产1区2区3区精品美女| 丰满少妇在线观看资源站| 亚洲欧美在线另类| 天天看天天摸天天操| 午夜精品久久久久影视| 亚洲一级视频在线观看| 亚洲国产精品嫩草影院久久| aⅴ在线视频男人的天堂| 久久久久一本一区二区青青蜜月| 99热播精品免费| 激情伦成人综合小说| 91超碰成人| 好男人www社区| 99麻豆久久久国产精品免费 | 日本不卡视频在线播放| 日本成人精品| 亚洲国产精品www| 国产成人影院| 欧美另类videosbestsex日本| 久久久久午夜电影| 99蜜桃臀久久久欧美精品网站| 香蕉久久a毛片| 亚洲天堂一区二区在线观看| 国产精品一区二区免费不卡 | 天天av综合| 亚洲欧美国产一区二区| 国产日韩精品视频一区二区三区 | 国产精品久久久久9999爆乳| 欧美日韩网站| 日本中文字幕高清| 久久成人精品无人区| 涩涩网站在线看| 国产日韩欧美精品在线| 久久国产精品系列| 日韩视频免费观看高清在线视频| a视频网址在线观看| 欧美亚洲在线视频| 久久精品论坛| 日韩精品在线观看av| 国产一区二区三区四区五区入口| 女人裸体性做爰全过| 亚洲精品一二三四区| 亚洲一区二区人妻| 最近2019中文字幕第三页视频| 日韩国产激情| 欧美日产一区二区三区在线观看| 在线一区视频| 精品国产av色一区二区深夜久久| 亚洲一区二区三区三| www.欧美色| 日韩国产精品一区| 在线天堂中文资源最新版| 国内精品久久久久久久果冻传媒| 亚洲激情av| 久热精品在线播放| 国产成人亚洲精品青草天美| 亚洲熟女乱综合一区二区三区 | 天堂网中文字幕| 亚洲精品国产精品自产a区红杏吧 亚洲精品国产精品乱码不99按摩 亚洲精品国产精品久久清纯直播 亚洲精品国产精品国自产在线 | 午夜影视日本亚洲欧洲精品| 国产高清在线免费| 亚洲美女喷白浆| 男女羞羞在线观看| 欧美不卡在线一区二区三区| 老司机午夜免费精品视频| 亚洲av无码一区二区三区人 | 韩国中文字幕hd久久精品| 亚洲2020天天堂在线观看| 日韩黄色网络| 91视频免费版污| 专区另类欧美日韩| 精品国自产在线观看| 97免费在线视频| 狼人精品一区二区三区在线| 岳毛多又紧做起爽| 国产成人免费网站| xxxxxx国产| 欧美一级视频精品观看| gogo在线高清视频| 国产精品国产精品国产专区蜜臀ah | 日韩精品久久久久久久的张开腿让 | 欧美一区二区视频网站| 性爱视频在线播放| 久久久综合香蕉尹人综合网| 秋霞午夜鲁丝一区二区老狼| 国产大片免费看| 精品视频在线播放免| 在线网址91| 国产精品一区二区久久久| 日韩一区二区在线| 欧美黄色一级片视频| 成人欧美一区二区三区视频网页| 精品毛片在线观看| 欧洲精品久久久| 亚洲成人av| 国产毛片毛片毛片毛片毛片毛片| 欧美色涩在线第一页| 午夜av在线免费观看| 日韩和欧美的一区二区| 米奇777在线欧美播放| 日韩无码精品一区二区| 亚洲综合一二区| 免费成人av电影| 亚洲一区中文字幕| 人人精品人人爱| 久久99久久久| 日韩欧美一区二区三区在线| 亚洲欧洲自拍|